ticket49073_test.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. DEBUGGING = False
  14. GROUP_DN = ("cn=group," + DEFAULT_SUFFIX)
  15. if DEBUGGING:
  16. logging.getLogger(__name__).setLevel(logging.DEBUG)
  17. else:
  18. logging.getLogger(__name__).setLevel(logging.INFO)
  19. log = logging.getLogger(__name__)
  20. class TopologyReplication(object):
  21. def __init__(self, master1, master2):
  22. master1.open()
  23. self.master1 = master1
  24. master2.open()
  25. self.master2 = master2
  26. @pytest.fixture(scope="module")
  27. def topology(request):
  28. """Create Replication Deployment"""
  29. # Creating master 1...
  30. if DEBUGGING:
  31. master1 = DirSrv(verbose=True)
  32. else:
  33. master1 = DirSrv(verbose=False)
  34. args_instance[SER_HOST] = HOST_MASTER_1
  35. args_instance[SER_PORT] = PORT_MASTER_1
  36. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  37. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  38. args_master = args_instance.copy()
  39. master1.allocate(args_master)
  40. instance_master1 = master1.exists()
  41. if instance_master1:
  42. master1.delete()
  43. master1.create()
  44. master1.open()
  45. master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  46. # Creating master 2...
  47. if DEBUGGING:
  48. master2 = DirSrv(verbose=True)
  49. else:
  50. master2 = DirSrv(verbose=False)
  51. args_instance[SER_HOST] = HOST_MASTER_2
  52. args_instance[SER_PORT] = PORT_MASTER_2
  53. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
  54. args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
  55. args_master = args_instance.copy()
  56. master2.allocate(args_master)
  57. instance_master2 = master2.exists()
  58. if instance_master2:
  59. master2.delete()
  60. master2.create()
  61. master2.open()
  62. master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
  63. def fin():
  64. """If we are debugging just stop the instances,
  65. otherwise remove them
  66. """
  67. if DEBUGGING:
  68. master1.stop()
  69. master2.stop()
  70. else:
  71. #master1.delete()
  72. #master2.delete()
  73. pass
  74. request.addfinalizer(fin)
  75. # Create all the agreements
  76. # Creating agreement from master 1 to master 2
  77. properties = {RA_NAME: 'meTo_' + master2.host + ':' + str(master2.port),
  78. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  79. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  80. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  81. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  82. m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
  83. if not m1_m2_agmt:
  84. log.fatal("Fail to create a master -> master replica agreement")
  85. sys.exit(1)
  86. log.debug("%s created" % m1_m2_agmt)
  87. # Creating agreement from master 2 to master 1
  88. properties = {RA_NAME: 'meTo_' + master1.host + ':' + str(master1.port),
  89. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  90. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  91. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  92. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  93. m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
  94. if not m2_m1_agmt:
  95. log.fatal("Fail to create a master -> master replica agreement")
  96. sys.exit(1)
  97. log.debug("%s created" % m2_m1_agmt)
  98. # Allow the replicas to get situated with the new agreements...
  99. time.sleep(5)
  100. # Initialize all the agreements
  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. # Clear out the tmp dir
  110. master1.clearTmpDir(__file__)
  111. return TopologyReplication(master1, master2)
  112. def _add_group_with_members(topology):
  113. # Create group
  114. try:
  115. topology.master1.add_s(Entry((GROUP_DN,
  116. {'objectclass': 'top groupofnames'.split(),
  117. 'cn': 'group'})))
  118. except ldap.LDAPError as e:
  119. log.fatal('Failed to add group: error ' + e.message['desc'])
  120. assert False
  121. # Add members to the group - set timeout
  122. log.info('Adding members to the group...')
  123. for idx in range(1, 5):
  124. try:
  125. MEMBER_VAL = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
  126. topology.master1.modify_s(GROUP_DN,
  127. [(ldap.MOD_ADD,
  128. 'member',
  129. MEMBER_VAL)])
  130. except ldap.LDAPError as e:
  131. log.fatal('Failed to update group: member (%s) - error: %s' %
  132. (MEMBER_VAL, e.message['desc']))
  133. assert False
  134. def _check_memberof(master, presence_flag):
  135. # Check that members have memberof attribute on M1
  136. for idx in range(1, 5):
  137. try:
  138. USER_DN = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
  139. ent = master.getEntry(USER_DN, ldap.SCOPE_BASE, "(objectclass=*)")
  140. if presence_flag:
  141. assert ent.hasAttr('memberof') and ent.getValue('memberof') == GROUP_DN
  142. else:
  143. assert not ent.hasAttr('memberof')
  144. except ldap.LDAPError as e:
  145. log.fatal('Failed to retrieve user (%s): error %s' % (USER_DN, e.message['desc']))
  146. assert False
  147. def _check_entry_exist(master, dn):
  148. attempt = 0
  149. while attempt <= 10:
  150. try:
  151. dn
  152. ent = master.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)")
  153. break
  154. except ldap.NO_SUCH_OBJECT:
  155. attempt = attempt + 1
  156. time.sleep(1)
  157. except ldap.LDAPError as e:
  158. log.fatal('Failed to retrieve user (%s): error %s' % (dn, e.message['desc']))
  159. assert False
  160. assert attempt != 10
  161. def test_ticket49073(topology):
  162. """Write your replication test here.
  163. To access each DirSrv instance use: topology.master1, topology.master2,
  164. ..., topology.hub1, ..., topology.consumer1,...
  165. Also, if you need any testcase initialization,
  166. please, write additional fixture for that(include finalizer).
  167. """
  168. topology.master1.plugins.enable(name=PLUGIN_MEMBER_OF)
  169. topology.master1.restart(timeout=10)
  170. topology.master2.plugins.enable(name=PLUGIN_MEMBER_OF)
  171. topology.master2.restart(timeout=10)
  172. # Configure fractional to prevent total init to send memberof
  173. ents = topology.master1.agreement.list(suffix=SUFFIX)
  174. assert len(ents) == 1
  175. log.info('update %s to add nsDS5ReplicatedAttributeListTotal' % ents[0].dn)
  176. topology.master1.modify_s(ents[0].dn,
  177. [(ldap.MOD_REPLACE,
  178. 'nsDS5ReplicatedAttributeListTotal',
  179. '(objectclass=*) $ EXCLUDE '),
  180. (ldap.MOD_REPLACE,
  181. 'nsDS5ReplicatedAttributeList',
  182. '(objectclass=*) $ EXCLUDE memberOf')])
  183. topology.master1.restart(timeout=10)
  184. #
  185. # create some users and a group
  186. #
  187. log.info('create users and group...')
  188. for idx in range(1, 5):
  189. try:
  190. USER_DN = ("uid=member%d,%s" % (idx, DEFAULT_SUFFIX))
  191. topology.master1.add_s(Entry((USER_DN,
  192. {'objectclass': 'top extensibleObject'.split(),
  193. 'uid': 'member%d' % (idx)})))
  194. except ldap.LDAPError as e:
  195. log.fatal('Failed to add user (%s): error %s' % (USER_DN, e.message['desc']))
  196. assert False
  197. _check_entry_exist(topology.master2, "uid=member4,%s" % (DEFAULT_SUFFIX))
  198. _add_group_with_members(topology)
  199. _check_entry_exist(topology.master2, GROUP_DN)
  200. # Check that for regular update memberof was on both side (because plugin is enabled both)
  201. time.sleep(5)
  202. _check_memberof(topology.master1, True)
  203. _check_memberof(topology.master2, True)
  204. # reinit with fractional definition
  205. ents = topology.master1.agreement.list(suffix=SUFFIX)
  206. assert len(ents) == 1
  207. topology.master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
  208. topology.master1.waitForReplInit(ents[0].dn)
  209. # Check that for total update memberof was on both side
  210. # because memberof is NOT excluded from total init
  211. time.sleep(5)
  212. _check_memberof(topology.master1, True)
  213. _check_memberof(topology.master2, True)
  214. if DEBUGGING:
  215. # Add debugging steps(if any)...
  216. pass
  217. if __name__ == '__main__':
  218. # Run isolated
  219. # -s for DEBUG mode
  220. CURRENT_FILE = os.path.realpath(__file__)
  221. pytest.main("-s %s" % CURRENT_FILE)