1
0

ticket48362_test.py 11 KB

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