ticket48226_test.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2015 Red Hat, Inc.
  3. # All rights reserved.
  4. #
  5. # License: GPL (version 3 or any later version).
  6. # See LICENSE for details.
  7. # --- END COPYRIGHT BLOCK ---
  8. #
  9. import os
  10. import sys
  11. import time
  12. import ldap
  13. import logging
  14. import pytest
  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 lib389.utils import *
  21. logging.getLogger(__name__).setLevel(logging.DEBUG)
  22. log = logging.getLogger(__name__)
  23. installation1_prefix = None
  24. class TopologyReplication(object):
  25. def __init__(self, master1, master2):
  26. master1.open()
  27. self.master1 = master1
  28. master2.open()
  29. self.master2 = master2
  30. @pytest.fixture(scope="module")
  31. def topology(request):
  32. global installation1_prefix
  33. os.environ['USE_VALGRIND'] = '1'
  34. if installation1_prefix:
  35. args_instance[SER_DEPLOYED_DIR] = installation1_prefix
  36. # Creating master 1...
  37. master1 = DirSrv(verbose=False)
  38. if installation1_prefix:
  39. args_instance[SER_DEPLOYED_DIR] = installation1_prefix
  40. args_instance[SER_HOST] = HOST_MASTER_1
  41. args_instance[SER_PORT] = PORT_MASTER_1
  42. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  43. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  44. args_master = args_instance.copy()
  45. master1.allocate(args_master)
  46. instance_master1 = master1.exists()
  47. if instance_master1:
  48. master1.delete()
  49. master1.create()
  50. master1.open()
  51. master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  52. # Creating master 2...
  53. master2 = DirSrv(verbose=False)
  54. if installation1_prefix:
  55. args_instance[SER_DEPLOYED_DIR] = installation1_prefix
  56. args_instance[SER_HOST] = HOST_MASTER_2
  57. args_instance[SER_PORT] = PORT_MASTER_2
  58. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
  59. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  60. args_master = args_instance.copy()
  61. master2.allocate(args_master)
  62. instance_master2 = master2.exists()
  63. if instance_master2:
  64. master2.delete()
  65. master2.create()
  66. master2.open()
  67. master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
  68. #
  69. # Create all the agreements
  70. #
  71. # Creating agreement from master 1 to master 2
  72. properties = {RA_NAME: r'meTo_$host:$port',
  73. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  74. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  75. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  76. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  77. m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
  78. if not m1_m2_agmt:
  79. log.fatal("Fail to create a master -> master replica agreement")
  80. sys.exit(1)
  81. log.debug("%s created" % m1_m2_agmt)
  82. # Creating agreement from master 2 to master 1
  83. properties = {RA_NAME: r'meTo_$host:$port',
  84. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  85. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  86. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  87. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  88. m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
  89. if not m2_m1_agmt:
  90. log.fatal("Fail to create a master -> master replica agreement")
  91. sys.exit(1)
  92. log.debug("%s created" % m2_m1_agmt)
  93. # Allow the replicas to get situated with the new agreements...
  94. time.sleep(5)
  95. #
  96. # Initialize all the agreements
  97. #
  98. master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
  99. master1.waitForReplInit(m1_m2_agmt)
  100. def fin():
  101. master1.delete()
  102. master2.delete()
  103. sbin_dir = master2.get_sbin_dir()
  104. if not master2.has_asan():
  105. valgrind_disable(sbin_dir)
  106. request.addfinalizer(fin)
  107. # Check replication is working...
  108. if master1.testReplication(DEFAULT_SUFFIX, master2):
  109. log.info('Replication is working.')
  110. else:
  111. log.fatal('Replication is not working.')
  112. assert False
  113. return TopologyReplication(master1, master2)
  114. def test_ticket48226_set_purgedelay(topology):
  115. args = {REPLICA_PURGE_DELAY: '5',
  116. REPLICA_PURGE_INTERVAL: '5'}
  117. try:
  118. topology.master1.replica.setProperties(DEFAULT_SUFFIX, None, None, args)
  119. except:
  120. log.fatal('Failed to configure replica')
  121. assert False
  122. try:
  123. topology.master2.replica.setProperties(DEFAULT_SUFFIX, None, None, args)
  124. except:
  125. log.fatal('Failed to configure replica')
  126. assert False
  127. topology.master1.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-auditlog-logging-enabled', 'on')])
  128. topology.master2.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-auditlog-logging-enabled', 'on')])
  129. topology.master1.restart(30)
  130. topology.master2.restart(30)
  131. def test_ticket48226_1(topology):
  132. name = 'test_entry'
  133. dn = "cn=%s,%s" % (name, SUFFIX)
  134. topology.master1.add_s(Entry((dn, {'objectclass': "top person".split(),
  135. 'sn': name,
  136. 'cn': name})))
  137. # First do an update that is replicated
  138. mods = [(ldap.MOD_ADD, 'description', '5')]
  139. topology.master1.modify_s(dn, mods)
  140. nbtry = 0
  141. while (nbtry <= 10):
  142. try:
  143. ent = topology.master2.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)", ['description'])
  144. if ent.hasAttr('description') and ent.getValue('description') == '5':
  145. break
  146. except ldap.NO_SUCH_OBJECT:
  147. pass
  148. nbtry = nbtry + 1
  149. time.sleep(1)
  150. assert nbtry <= 10
  151. # Stop M2 so that it will not receive the next update
  152. topology.master2.stop(10)
  153. # ADD a new value that is not replicated
  154. mods = [(ldap.MOD_DELETE, 'description', '5')]
  155. topology.master1.modify_s(dn, mods)
  156. # Stop M1 so that it will keep del '5' that is unknown from master2
  157. topology.master1.stop(10)
  158. # Get the sbin directory so we know where to replace 'ns-slapd'
  159. sbin_dir = topology.master2.get_sbin_dir()
  160. # Enable valgrind
  161. if not topology.master2.has_asan():
  162. valgrind_enable(sbin_dir)
  163. # start M2 to do the next updates
  164. topology.master2.start()
  165. # ADD 'description' by '5'
  166. mods = [(ldap.MOD_DELETE, 'description', '5')]
  167. topology.master2.modify_s(dn, mods)
  168. # DEL 'description' by '5'
  169. mods = [(ldap.MOD_ADD, 'description', '5')]
  170. topology.master2.modify_s(dn, mods)
  171. # sleep of purge delay so that the next update will purge the CSN_7
  172. time.sleep(6)
  173. # ADD 'description' by '6' that purge the state info
  174. mods = [(ldap.MOD_ADD, 'description', '6')]
  175. topology.master2.modify_s(dn, mods)
  176. # Restart master1
  177. #topology.master1.start(30)
  178. if not topology.master2.has_asan():
  179. results_file = valgrind_get_results_file(topology.master2)
  180. # Stop master2
  181. topology.master2.stop(30)
  182. # Check for leak
  183. if not topology.master2.has_asan():
  184. if valgrind_check_file(results_file, VALGRIND_LEAK_STR, 'csnset_dup'):
  185. log.info('Valgrind reported leak in csnset_dup!')
  186. assert False
  187. else:
  188. log.info('Valgrind is happy!')
  189. # Check for invalid read/write
  190. if valgrind_check_file(results_file, VALGRIND_INVALID_STR, 'csnset_dup'):
  191. log.info('Valgrind reported invalid!')
  192. assert False
  193. else:
  194. log.info('Valgrind is happy!')
  195. # Check for invalid read/write
  196. if valgrind_check_file(results_file, VALGRIND_INVALID_STR, 'csnset_free'):
  197. log.info('Valgrind reported invalid!')
  198. assert False
  199. else:
  200. log.info('Valgrind is happy!')
  201. log.info('Testcase PASSED')
  202. if __name__ == '__main__':
  203. # Run isolated
  204. # -s for DEBUG mode
  205. CURRENT_FILE = os.path.realpath(__file__)
  206. pytest.main("-s %s" % CURRENT_FILE)