ticket47781_test.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import os
  2. import sys
  3. import time
  4. import ldap
  5. import logging
  6. import socket
  7. import pytest
  8. from lib389 import DirSrv, Entry, tools, tasks
  9. from lib389.tools import DirSrvTools
  10. from lib389._constants import *
  11. from lib389.properties import *
  12. from lib389.tasks import *
  13. from constants import *
  14. log = logging.getLogger(__name__)
  15. installation_prefix = None
  16. class TopologyStandalone(object):
  17. def __init__(self, standalone):
  18. standalone.open()
  19. self.standalone = standalone
  20. @pytest.fixture(scope="module")
  21. def topology(request):
  22. '''
  23. This fixture is used to standalone topology for the 'module'.
  24. At the beginning, It may exists a standalone instance.
  25. It may also exists a backup for the standalone instance.
  26. Principle:
  27. If standalone instance exists:
  28. restart it
  29. If backup of standalone exists:
  30. create/rebind to standalone
  31. restore standalone instance from backup
  32. else:
  33. Cleanup everything
  34. remove instance
  35. remove backup
  36. Create instance
  37. Create backup
  38. '''
  39. global installation_prefix
  40. if installation_prefix:
  41. args_instance[SER_DEPLOYED_DIR] = installation_prefix
  42. standalone = DirSrv(verbose=False)
  43. # Args for the standalone instance
  44. args_instance[SER_HOST] = HOST_STANDALONE
  45. args_instance[SER_PORT] = PORT_STANDALONE
  46. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  47. args_standalone = args_instance.copy()
  48. standalone.allocate(args_standalone)
  49. # Get the status of the backups
  50. backup_standalone = standalone.checkBackupFS()
  51. # Get the status of the instance and restart it if it exists
  52. instance_standalone = standalone.exists()
  53. if instance_standalone:
  54. # assuming the instance is already stopped, just wait 5 sec max
  55. standalone.stop(timeout=5)
  56. standalone.start(timeout=10)
  57. if backup_standalone:
  58. # The backup exist, assuming it is correct
  59. # we just re-init the instance with it
  60. if not instance_standalone:
  61. standalone.create()
  62. # Used to retrieve configuration information (dbdir, confdir...)
  63. standalone.open()
  64. # restore standalone instance from backup
  65. standalone.stop(timeout=10)
  66. standalone.restoreFS(backup_standalone)
  67. standalone.start(timeout=10)
  68. else:
  69. # We should be here only in two conditions
  70. # - This is the first time a test involve standalone instance
  71. # - Something weird happened (instance/backup destroyed)
  72. # so we discard everything and recreate all
  73. # Remove the backup. So even if we have a specific backup file
  74. # (e.g backup_standalone) we clear backup that an instance may have created
  75. if backup_standalone:
  76. standalone.clearBackupFS()
  77. # Remove the instance
  78. if instance_standalone:
  79. standalone.delete()
  80. # Create the instance
  81. standalone.create()
  82. # Used to retrieve configuration information (dbdir, confdir...)
  83. standalone.open()
  84. # Time to create the backups
  85. standalone.stop(timeout=10)
  86. standalone.backupfile = standalone.backupFS()
  87. standalone.start(timeout=10)
  88. #
  89. # Here we have standalone instance up and running
  90. # Either coming from a backup recovery
  91. # or from a fresh (re)init
  92. # Time to return the topology
  93. return TopologyStandalone(standalone)
  94. def test_ticket47781(topology):
  95. """
  96. Testing for a deadlock after doing an online import of an LDIF with
  97. replication data. The replication agreement should be invalid.
  98. """
  99. log.info('Testing Ticket 47781 - Testing for deadlock after importing LDIF with replication data')
  100. #
  101. # Setup Replication
  102. #
  103. log.info('Setting up replication...')
  104. topology.standalone.replica.enableReplication(suffix=DEFAULT_SUFFIX, role=REPLICAROLE_MASTER,
  105. replicaId=REPLICAID_MASTER_1)
  106. properties = {RA_NAME: r'meTo_$host:$port',
  107. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  108. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  109. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  110. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  111. # The agreement should point to a server that does NOT exist (invalid port)
  112. repl_agreement = topology.standalone.agreement.create(suffix=DEFAULT_SUFFIX,
  113. host=topology.standalone.host,
  114. port=5555,
  115. properties=properties)
  116. #
  117. # add two entries
  118. #
  119. log.info('Adding two entries...')
  120. try:
  121. topology.standalone.add_s(Entry(('cn=entry1,dc=example,dc=com', {
  122. 'objectclass': 'top person'.split(),
  123. 'sn': 'user',
  124. 'cn': 'entry1'})))
  125. except ldap.LDAPError, e:
  126. log.error('Failed to add entry 1: ' + e.message['desc'])
  127. assert False
  128. try:
  129. topology.standalone.add_s(Entry(('cn=entry2,dc=example,dc=com', {
  130. 'objectclass': 'top person'.split(),
  131. 'sn': 'user',
  132. 'cn': 'entry2'})))
  133. except ldap.LDAPError, e:
  134. log.error('Failed to add entry 2: ' + e.message['desc'])
  135. assert False
  136. #
  137. # export the replication ldif
  138. #
  139. log.info('Exporting replication ldif...')
  140. args = {EXPORT_REPL_INFO: True}
  141. exportTask = Tasks(topology.standalone)
  142. try:
  143. exportTask.exportLDIF(DEFAULT_SUFFIX, None, "/tmp/export.ldif", args)
  144. except ValueError:
  145. assert False
  146. #
  147. # Restart the server
  148. #
  149. log.info('Restarting server...')
  150. topology.standalone.stop(timeout=5)
  151. topology.standalone.start(timeout=5)
  152. #
  153. # Import the ldif
  154. #
  155. log.info('Import replication LDIF file...')
  156. importTask = Tasks(topology.standalone)
  157. args = {TASK_WAIT: True}
  158. try:
  159. importTask.importLDIF(DEFAULT_SUFFIX, None, "/tmp/export.ldif", args)
  160. os.remove("/tmp/export.ldif")
  161. except ValueError:
  162. os.remove("/tmp/export.ldif")
  163. assert False
  164. #
  165. # Search for tombstones - we should not hang/timeout
  166. #
  167. log.info('Search for tombstone entries(should find one and not hang)...')
  168. topology.standalone.set_option(ldap.OPT_NETWORK_TIMEOUT, 5);
  169. topology.standalone.set_option(ldap.OPT_TIMEOUT, 5);
  170. try:
  171. entries = topology.standalone.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, 'objectclass=nsTombstone')
  172. if not entries:
  173. log.fatal('Search failed to find any entries.')
  174. assert PR_False
  175. except ldap.LDAPError, e:
  176. log.fatal('Search failed: ' + e.message['desc'])
  177. assert PR_False
  178. # If we got here we passed!
  179. log.info('Ticket47781 Test - Passed')
  180. def test_ticket47781_final(topology):
  181. topology.standalone.stop(timeout=10)
  182. def run_isolated():
  183. '''
  184. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  185. To run isolated without py.test, you need to
  186. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  187. - set the installation prefix
  188. - run this program
  189. '''
  190. global installation_prefix
  191. installation_prefix = None
  192. topo = topology(True)
  193. test_ticket47781(topo)
  194. if __name__ == '__main__':
  195. run_isolated()