ticket47871_test.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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. '''
  10. Created on Nov 7, 2013
  11. @author: tbordaz
  12. '''
  13. import os
  14. import sys
  15. import time
  16. import ldap
  17. import logging
  18. import pytest
  19. from lib389 import DirSrv, Entry, tools
  20. from lib389.tools import DirSrvTools
  21. from lib389._constants import *
  22. from lib389.properties import *
  23. logging.getLogger(__name__).setLevel(logging.DEBUG)
  24. log = logging.getLogger(__name__)
  25. TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
  26. ENTRY_DN = "cn=test_entry, %s" % SUFFIX
  27. OTHER_NAME = 'other_entry'
  28. MAX_OTHERS = 10
  29. ATTRIBUTES = ['street', 'countryName', 'description', 'postalAddress', 'postalCode', 'title', 'l', 'roomNumber']
  30. class TopologyMasterConsumer(object):
  31. def __init__(self, master, consumer):
  32. master.open()
  33. self.master = master
  34. consumer.open()
  35. self.consumer = consumer
  36. def __repr__(self):
  37. return "Master[%s] -> Consumer[%s" % (self.master, self.consumer)
  38. @pytest.fixture(scope="module")
  39. def topology(request):
  40. '''
  41. This fixture is used to create a replicated topology for the 'module'.
  42. The replicated topology is MASTER -> Consumer.
  43. '''
  44. master = DirSrv(verbose=False)
  45. consumer = DirSrv(verbose=False)
  46. # Args for the master instance
  47. args_instance[SER_HOST] = HOST_MASTER_1
  48. args_instance[SER_PORT] = PORT_MASTER_1
  49. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  50. args_master = args_instance.copy()
  51. master.allocate(args_master)
  52. # Args for the consumer instance
  53. args_instance[SER_HOST] = HOST_CONSUMER_1
  54. args_instance[SER_PORT] = PORT_CONSUMER_1
  55. args_instance[SER_SERVERID_PROP] = SERVERID_CONSUMER_1
  56. args_consumer = args_instance.copy()
  57. consumer.allocate(args_consumer)
  58. # Get the status of the instance and restart it if it exists
  59. instance_master = master.exists()
  60. instance_consumer = consumer.exists()
  61. # Remove all the instances
  62. if instance_master:
  63. master.delete()
  64. if instance_consumer:
  65. consumer.delete()
  66. # Create the instances
  67. master.create()
  68. master.open()
  69. consumer.create()
  70. consumer.open()
  71. #
  72. # Now prepare the Master-Consumer topology
  73. #
  74. # First Enable replication
  75. master.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  76. consumer.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_CONSUMER)
  77. # Initialize the supplier->consumer
  78. properties = {RA_NAME: r'meTo_$host:$port',
  79. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  80. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  81. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  82. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  83. repl_agreement = master.agreement.create(suffix=SUFFIX, host=consumer.host, port=consumer.port, properties=properties)
  84. if not repl_agreement:
  85. log.fatal("Fail to create a replica agreement")
  86. sys.exit(1)
  87. log.debug("%s created" % repl_agreement)
  88. master.agreement.init(SUFFIX, HOST_CONSUMER_1, PORT_CONSUMER_1)
  89. master.waitForReplInit(repl_agreement)
  90. # Check replication is working fine
  91. if master.testReplication(DEFAULT_SUFFIX, consumer):
  92. log.info('Replication is working.')
  93. else:
  94. log.fatal('Replication is not working.')
  95. assert False
  96. def fin():
  97. master.delete()
  98. consumer.delete()
  99. request.addfinalizer(fin)
  100. #
  101. # Here we have two instances master and consumer
  102. # with replication working. Either coming from a backup recovery
  103. # or from a fresh (re)init
  104. # Time to return the topology
  105. return TopologyMasterConsumer(master, consumer)
  106. def test_ticket47871_init(topology):
  107. """
  108. Initialize the test environment
  109. """
  110. topology.master.plugins.enable(name=PLUGIN_RETRO_CHANGELOG)
  111. mod = [(ldap.MOD_REPLACE, 'nsslapd-changelogmaxage', "10s"), # 10 second triming
  112. (ldap.MOD_REPLACE, 'nsslapd-changelog-trim-interval', "5s")]
  113. topology.master.modify_s("cn=%s,%s" % (PLUGIN_RETRO_CHANGELOG, DN_PLUGIN), mod)
  114. #topology.master.plugins.enable(name=PLUGIN_MEMBER_OF)
  115. #topology.master.plugins.enable(name=PLUGIN_REFER_INTEGRITY)
  116. topology.master.stop(timeout=10)
  117. topology.master.start(timeout=10)
  118. topology.master.log.info("test_ticket47871_init topology %r" % (topology))
  119. # the test case will check if a warning message is logged in the
  120. # error log of the supplier
  121. topology.master.errorlog_file = open(topology.master.errlog, "r")
  122. def test_ticket47871_1(topology):
  123. '''
  124. ADD entries and check they are all in the retrocl
  125. '''
  126. # add dummy entries
  127. for cpt in range(MAX_OTHERS):
  128. name = "%s%d" % (OTHER_NAME, cpt)
  129. topology.master.add_s(Entry(("cn=%s,%s" % (name, SUFFIX), {
  130. 'objectclass': "top person".split(),
  131. 'sn': name,
  132. 'cn': name})))
  133. topology.master.log.info("test_ticket47871_init: %d entries ADDed %s[0..%d]" % (MAX_OTHERS, OTHER_NAME, MAX_OTHERS - 1))
  134. # Check the number of entries in the retro changelog
  135. time.sleep(1)
  136. ents = topology.master.search_s(RETROCL_SUFFIX, ldap.SCOPE_ONELEVEL, "(objectclass=*)")
  137. assert len(ents) == MAX_OTHERS
  138. topology.master.log.info("Added entries are")
  139. for ent in ents:
  140. topology.master.log.info("%s" % ent.dn)
  141. def test_ticket47871_2(topology):
  142. '''
  143. Wait until there is just a last entries
  144. '''
  145. MAX_TRIES = 10
  146. TRY_NO = 1
  147. while TRY_NO <= MAX_TRIES:
  148. time.sleep(6) # at least 1 trimming occurred
  149. ents = topology.master.search_s(RETROCL_SUFFIX, ldap.SCOPE_ONELEVEL, "(objectclass=*)")
  150. assert len(ents) <= MAX_OTHERS
  151. topology.master.log.info("\nTry no %d it remains %d entries" % (TRY_NO, len(ents)))
  152. for ent in ents:
  153. topology.master.log.info("%s" % ent.dn)
  154. if len(ents) > 1:
  155. TRY_NO += 1
  156. else:
  157. break
  158. assert TRY_NO <= MAX_TRIES
  159. assert len(ents) <= 1
  160. if __name__ == '__main__':
  161. # Run isolated
  162. # -s for DEBUG mode
  163. CURRENT_FILE = os.path.realpath(__file__)
  164. pytest.main("-s %s" % CURRENT_FILE)