ticket48362_test.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import os
  2. import sys
  3. import time
  4. import ldap
  5. import logging
  6. import pytest
  7. from lib389 import DirSrv, Entry, tools, tasks
  8. from lib389.tools import DirSrvTools
  9. from lib389._constants import *
  10. from lib389.properties import *
  11. from lib389.tasks import *
  12. from lib389.utils import *
  13. logging.getLogger(__name__).setLevel(logging.DEBUG)
  14. log = logging.getLogger(__name__)
  15. PEOPLE_OU='people'
  16. PEOPLE_DN = "ou=%s,%s" % (PEOPLE_OU, SUFFIX)
  17. MAX_ACCOUNTS=5
  18. BINDMETHOD_ATTR = 'dnaRemoteBindMethod'
  19. BINDMETHOD_VALUE = "SASL/GSSAPI"
  20. PROTOCOLE_ATTR = 'dnaRemoteConnProtocol'
  21. PROTOCOLE_VALUE = 'LDAP'
  22. class TopologyReplication(object):
  23. def __init__(self, master1, master2):
  24. master1.open()
  25. self.master1 = master1
  26. master2.open()
  27. self.master2 = master2
  28. @pytest.fixture(scope="module")
  29. def topology(request):
  30. # Creating master 1...
  31. master1 = DirSrv(verbose=False)
  32. args_instance[SER_HOST] = HOST_MASTER_1
  33. args_instance[SER_PORT] = PORT_MASTER_1
  34. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  35. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  36. args_master = args_instance.copy()
  37. master1.allocate(args_master)
  38. instance_master1 = master1.exists()
  39. if instance_master1:
  40. master1.delete()
  41. master1.create()
  42. master1.open()
  43. master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  44. # Creating master 2...
  45. master2 = DirSrv(verbose=False)
  46. args_instance[SER_HOST] = HOST_MASTER_2
  47. args_instance[SER_PORT] = PORT_MASTER_2
  48. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
  49. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  50. args_master = args_instance.copy()
  51. master2.allocate(args_master)
  52. instance_master2 = master2.exists()
  53. if instance_master2:
  54. master2.delete()
  55. master2.create()
  56. master2.open()
  57. master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
  58. #
  59. # Create all the agreements
  60. #
  61. # Creating agreement from master 1 to master 2
  62. properties = {RA_NAME: r'meTo_$host:$port',
  63. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  64. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  65. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  66. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  67. m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
  68. if not m1_m2_agmt:
  69. log.fatal("Fail to create a master -> master replica agreement")
  70. sys.exit(1)
  71. log.debug("%s created" % m1_m2_agmt)
  72. # Creating agreement from master 2 to master 1
  73. properties = {RA_NAME: r'meTo_$host:$port',
  74. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  75. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  76. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  77. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  78. m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
  79. if not m2_m1_agmt:
  80. log.fatal("Fail to create a master -> master replica agreement")
  81. sys.exit(1)
  82. log.debug("%s created" % m2_m1_agmt)
  83. # Allow the replicas to get situated with the new agreements...
  84. time.sleep(5)
  85. #
  86. # Initialize all the agreements
  87. #
  88. master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
  89. master1.waitForReplInit(m1_m2_agmt)
  90. # Check replication is working...
  91. if master1.testReplication(DEFAULT_SUFFIX, master2):
  92. log.info('Replication is working.')
  93. else:
  94. log.fatal('Replication is not working.')
  95. assert False
  96. # Delete each instance in the end
  97. def fin():
  98. master1.delete()
  99. master2.delete()
  100. #request.addfinalizer(fin)
  101. # Clear out the tmp dir
  102. master1.clearTmpDir(__file__)
  103. return TopologyReplication(master1, master2)
  104. def _dna_config(server, nextValue=500, maxValue=510):
  105. log.info("Add dna plugin config entry...%s" % server)
  106. cfg_base_dn = 'cn=dna config,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config'
  107. try:
  108. server.add_s(Entry((cfg_base_dn, {
  109. 'objectclass': 'top dnaPluginConfig'.split(),
  110. 'dnaType': 'description',
  111. 'dnaMagicRegen': '-1',
  112. 'dnaFilter': '(objectclass=posixAccount)',
  113. 'dnaScope': 'ou=people,%s' % SUFFIX,
  114. 'dnaNextValue': str(nextValue),
  115. 'dnaMaxValue' : str(nextValue+maxValue),
  116. 'dnaSharedCfgDN': 'ou=ranges,%s' % SUFFIX
  117. })))
  118. except ldap.LDAPError as e:
  119. log.error('Failed to add DNA config entry: error ' + e.message['desc'])
  120. assert False
  121. log.info("Enable the DNA plugin...")
  122. try:
  123. server.plugins.enable(name=PLUGIN_DNA)
  124. except e:
  125. log.error("Failed to enable DNA Plugin: error " + e.message['desc'])
  126. assert False
  127. log.info("Restarting the server...")
  128. server.stop(timeout=120)
  129. time.sleep(1)
  130. server.start(timeout=120)
  131. time.sleep(3)
  132. SHARE_CFG_BASE = 'ou=ranges,' + SUFFIX
  133. def _wait_shared_cfg_servers(server, expected):
  134. attempts = 0
  135. ents = []
  136. try:
  137. ents = server.search_s(SHARE_CFG_BASE, ldap.SCOPE_ONELEVEL, "(objectclass=*)")
  138. except ldap.NO_SUCH_OBJECT:
  139. pass
  140. except lib389.NoSuchEntryError:
  141. pass
  142. while (len(ents) != expected):
  143. assert attempts < 10
  144. time.sleep(5)
  145. try:
  146. ents = server.search_s(SHARE_CFG_BASE, ldap.SCOPE_ONELEVEL, "(objectclass=*)")
  147. except ldap.NO_SUCH_OBJECT:
  148. pass
  149. except lib389.NoSuchEntryError:
  150. pass
  151. def _shared_cfg_server_update(server, method=BINDMETHOD_VALUE, transport=PROTOCOLE_VALUE):
  152. log.info('\n======================== Update dnaPortNum=%d ============================\n'% server.port)
  153. try:
  154. ent = server.getEntry(SHARE_CFG_BASE, ldap.SCOPE_ONELEVEL, "(dnaPortNum=%d)" % server.port)
  155. mod = [(ldap.MOD_REPLACE, BINDMETHOD_ATTR, method),
  156. (ldap.MOD_REPLACE, PROTOCOLE_ATTR, transport)]
  157. server.modify_s(ent.dn, mod)
  158. log.info('\n======================== Update done\n')
  159. ent = server.getEntry(SHARE_CFG_BASE, ldap.SCOPE_ONELEVEL, "(dnaPortNum=%d)" % server.port)
  160. except ldap.NO_SUCH_OBJECT:
  161. log.fatal("Unknown host")
  162. assert False
  163. def test_ticket48362(topology):
  164. """Write your replication testcase here.
  165. To access each DirSrv instance use: topology.master1, topology.master2,
  166. ..., topology.hub1, ..., topology.consumer1, ...
  167. Also, if you need any testcase initialization,
  168. please, write additional fixture for that(include finalizer).
  169. """
  170. try:
  171. topology.master1.add_s(Entry((PEOPLE_DN, {
  172. 'objectclass': "top extensibleObject".split(),
  173. 'ou': 'people'})))
  174. except ldap.ALREADY_EXISTS:
  175. pass
  176. topology.master1.add_s(Entry((SHARE_CFG_BASE, {
  177. 'objectclass': 'top organizationalunit'.split(),
  178. 'ou': 'ranges'
  179. })))
  180. # master 1 will have a valid remaining range (i.e. 101)
  181. # master 2 will not have a valid remaining range (i.e. 0) so dna servers list on master2
  182. # will not contain master 2. So at restart, master 2 is recreated without the method/protocol attribute
  183. _dna_config(topology.master1, nextValue=1000, maxValue=100)
  184. _dna_config(topology.master2, nextValue=2000, maxValue=-1)
  185. # check we have all the servers available
  186. _wait_shared_cfg_servers(topology.master1, 2)
  187. _wait_shared_cfg_servers(topology.master2, 2)
  188. # now force the method/transport on the servers entry
  189. _shared_cfg_server_update(topology.master1)
  190. _shared_cfg_server_update(topology.master2)
  191. log.info('\n======================== BEFORE RESTART ============================\n')
  192. ent = topology.master1.getEntry(SHARE_CFG_BASE, ldap.SCOPE_ONELEVEL, "(dnaPortNum=%d)" % topology.master1.port)
  193. log.info('\n======================== BEFORE RESTART ============================\n')
  194. assert(ent.hasAttr(BINDMETHOD_ATTR) and ent.getValue(BINDMETHOD_ATTR) == BINDMETHOD_VALUE)
  195. assert(ent.hasAttr(PROTOCOLE_ATTR) and ent.getValue(PROTOCOLE_ATTR) == PROTOCOLE_VALUE)
  196. ent = topology.master2.getEntry(SHARE_CFG_BASE, ldap.SCOPE_ONELEVEL, "(dnaPortNum=%d)" % topology.master2.port)
  197. log.info('\n======================== BEFORE RESTART ============================\n')
  198. assert(ent.hasAttr(BINDMETHOD_ATTR) and ent.getValue(BINDMETHOD_ATTR) == BINDMETHOD_VALUE)
  199. assert(ent.hasAttr(PROTOCOLE_ATTR) and ent.getValue(PROTOCOLE_ATTR) == PROTOCOLE_VALUE)
  200. topology.master1.restart(10)
  201. topology.master2.restart(10)
  202. # to allow DNA plugin to recreate the local host entry
  203. time.sleep(40)
  204. log.info('\n=================== AFTER RESTART =================================\n')
  205. ent = topology.master1.getEntry(SHARE_CFG_BASE, ldap.SCOPE_ONELEVEL, "(dnaPortNum=%d)" % topology.master1.port)
  206. log.info('\n=================== AFTER RESTART =================================\n')
  207. assert(ent.hasAttr(BINDMETHOD_ATTR) and ent.getValue(BINDMETHOD_ATTR) == BINDMETHOD_VALUE)
  208. assert(ent.hasAttr(PROTOCOLE_ATTR) and ent.getValue(PROTOCOLE_ATTR) == PROTOCOLE_VALUE)
  209. ent = topology.master2.getEntry(SHARE_CFG_BASE, ldap.SCOPE_ONELEVEL, "(dnaPortNum=%d)" % topology.master2.port)
  210. log.info('\n=================== AFTER RESTART =================================\n')
  211. assert(ent.hasAttr(BINDMETHOD_ATTR) and ent.getValue(BINDMETHOD_ATTR) == BINDMETHOD_VALUE)
  212. assert(ent.hasAttr(PROTOCOLE_ATTR) and ent.getValue(PROTOCOLE_ATTR) == PROTOCOLE_VALUE)
  213. log.info('Test complete')
  214. if __name__ == '__main__':
  215. # Run isolated
  216. # -s for DEBUG mode
  217. CURRENT_FILE = os.path.realpath(__file__)
  218. pytest.main("-s %s" % CURRENT_FILE)