ticket48326_test.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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 shlex
  13. import subprocess
  14. import ldap
  15. import logging
  16. import pytest
  17. from lib389 import DirSrv, Entry, tools, tasks
  18. from lib389.tools import DirSrvTools
  19. from lib389._constants import *
  20. from lib389.properties import *
  21. from lib389.tasks import *
  22. from lib389.utils import *
  23. logging.getLogger(__name__).setLevel(logging.DEBUG)
  24. log = logging.getLogger(__name__)
  25. installation1_prefix = None
  26. MYDN = 'uid=tuser1M,dc=example,dc=com'
  27. MYLDIF = 'ticket48326.ldif'
  28. class TopologyReplication(object):
  29. def __init__(self, master1, master2):
  30. master1.open()
  31. self.master1 = master1
  32. master2.open()
  33. self.master2 = master2
  34. @pytest.fixture(scope="module")
  35. def topology(request):
  36. global installation1_prefix
  37. if installation1_prefix:
  38. args_instance[SER_DEPLOYED_DIR] = installation1_prefix
  39. # Creating master 1...
  40. master1 = DirSrv(verbose=False)
  41. if installation1_prefix:
  42. args_instance[SER_DEPLOYED_DIR] = installation1_prefix
  43. args_instance[SER_HOST] = HOST_MASTER_1
  44. args_instance[SER_PORT] = PORT_MASTER_1
  45. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  46. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  47. args_master = args_instance.copy()
  48. master1.allocate(args_master)
  49. instance_master1 = master1.exists()
  50. if instance_master1:
  51. master1.delete()
  52. master1.create()
  53. master1.open()
  54. master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  55. # Creating master 2...
  56. master2 = DirSrv(verbose=False)
  57. if installation1_prefix:
  58. args_instance[SER_DEPLOYED_DIR] = installation1_prefix
  59. args_instance[SER_HOST] = HOST_MASTER_2
  60. args_instance[SER_PORT] = PORT_MASTER_2
  61. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
  62. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  63. args_master = args_instance.copy()
  64. master2.allocate(args_master)
  65. instance_master2 = master2.exists()
  66. if instance_master2:
  67. master2.delete()
  68. master2.create()
  69. master2.open()
  70. master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
  71. #
  72. # Create all the agreements
  73. #
  74. # Creating agreement from master 1 to master 2
  75. properties = {RA_NAME: r'meTo_$host:$port',
  76. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  77. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  78. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  79. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  80. m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
  81. if not m1_m2_agmt:
  82. log.fatal("Fail to create a master -> master replica agreement")
  83. sys.exit(1)
  84. log.debug("%s created" % m1_m2_agmt)
  85. # Creating agreement from master 2 to master 1
  86. properties = {RA_NAME: r'meTo_$host:$port',
  87. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  88. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  89. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  90. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  91. m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
  92. if not m2_m1_agmt:
  93. log.fatal("Fail to create a master -> master replica agreement")
  94. sys.exit(1)
  95. log.debug("%s created" % m2_m1_agmt)
  96. # Allow the replicas to get situated with the new agreements...
  97. time.sleep(5)
  98. #
  99. # Initialize all the agreements
  100. #
  101. master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
  102. master1.waitForReplInit(m1_m2_agmt)
  103. # Check replication is working...
  104. if master1.testReplication(DEFAULT_SUFFIX, master2):
  105. log.info('Replication is working.')
  106. else:
  107. log.fatal('Replication is not working.')
  108. assert False
  109. # Delete each instance in the end
  110. def fin():
  111. master1.delete()
  112. master2.delete()
  113. request.addfinalizer(fin)
  114. # Clear out the tmp dir
  115. master1.clearTmpDir(__file__)
  116. return TopologyReplication(master1, master2)
  117. @pytest.fixture(scope="module")
  118. def add_entry(topology, server, serverPort, expectToFail):
  119. """
  120. Adding 1Mentry to the given server
  121. Check the add result based upon the expectToFail info.
  122. """
  123. if expectToFail:
  124. log.info("Adding 1M entry to %s expecting to fail." % server)
  125. else:
  126. log.info("Adding 1M entry to %s expecting to succeed." % server)
  127. data_dir_path = topology.master1.getDir(__file__, DATA_DIR)
  128. ldif_file = data_dir_path + MYLDIF
  129. #strcmdline = '/usr/bin/ldapmodify -x -h localhost -p' + str(serverPort) + '-D' + DN_DM + '-w' + PW_DM + '-af' + ldif_file
  130. #cmdline = shlex.split(strcmdline)
  131. cmdline = ['/usr/bin/ldapmodify', '-x', '-h', 'localhost', '-p', str(serverPort),
  132. '-D', DN_DM, '-w', PW_DM, '-af', ldif_file]
  133. log.info("Running cmdline (%s): %s" % (server, cmdline))
  134. try:
  135. proc = subprocess.Popen(cmdline, stderr=subprocess.PIPE)
  136. except Exception as e:
  137. log.info("%s caught in exception: %s" % (cmdline, e))
  138. assert False
  139. Found = False
  140. Expected = "ldap_result: Can't contact LDAP server"
  141. while True:
  142. l = proc.stderr.readline()
  143. if l == "":
  144. break
  145. if Expected in l:
  146. Found = True
  147. break
  148. if expectToFail:
  149. if Found:
  150. log.info("Adding 1M entry to %s failed as expected: %s" % (server, l))
  151. else:
  152. log.fatal("Expected error message %s was not returned: %s" % Expected)
  153. assert False
  154. else:
  155. if Found:
  156. log.fatal("%s failed although expecting to succeed: %s" % (cmdline, l))
  157. assert False
  158. else:
  159. log.info("Adding 1M entry to %s succeeded as expected" % server)
  160. def test_ticket48326(topology):
  161. """
  162. maxbersize is ignored in the replicated operations.
  163. [settings]
  164. master1 has default size maxbersize (2MB).
  165. master2 has much saller size maxbersize (20KB).
  166. [test case]
  167. Adding an entry which size is larger than 20KB to master2 fails.
  168. But adding an entry which size is larger than 20KB and less than 2MB to master1 succeeds
  169. and the entry is successfully replicated to master2.
  170. """
  171. log.info("Ticket 48326 - it could be nice to have nsslapd-maxbersize default to bigger than 2Mb")
  172. log.info("Set nsslapd-maxbersize: 20K to master2")
  173. try:
  174. topology.master2.modify_s("cn=config", [(ldap.MOD_REPLACE, 'nsslapd-maxbersize', '20480')])
  175. except ldap.LDAPError as e:
  176. log.error('Failed to set nsslapd-maxbersize == 20480: error ' + e.message['desc'])
  177. assert False
  178. add_entry(topology, "master2", PORT_MASTER_2, True)
  179. add_entry(topology, "master1", PORT_MASTER_1, False)
  180. time.sleep(1)
  181. log.info('Searching for %s on master2...', MYDN)
  182. try:
  183. entries = topology.master2.search_s(MYDN, ldap.SCOPE_BASE, '(objectclass=*)')
  184. if not entries:
  185. log.fatal('Entry %s failed to repliate to master2.' % MYDN)
  186. assert False
  187. else:
  188. log.info('SUCCESS: Entry %s is successfully replicated to master2.' % MYDN)
  189. except ldap.LDAPError as e:
  190. log.fatal('Search failed: ' + e.message['desc'])
  191. assert False
  192. if __name__ == '__main__':
  193. # Run isolated
  194. # -s for DEBUG mode
  195. CURRENT_FILE = os.path.realpath(__file__)
  196. pytest.main("-s %s" % CURRENT_FILE)