ticket47869MMR_test.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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 ldap
  13. import logging
  14. import pytest
  15. from lib389 import DirSrv, Entry, tools
  16. from lib389.tools import DirSrvTools
  17. from lib389._constants import *
  18. from lib389.properties import *
  19. logging.getLogger(__name__).setLevel(logging.DEBUG)
  20. log = logging.getLogger(__name__)
  21. #
  22. # important part. We can deploy Master1 and Master2 on different versions
  23. #
  24. installation1_prefix = None
  25. installation2_prefix = None
  26. TEST_REPL_DN = "cn=test_repl, %s" % SUFFIX
  27. ENTRY_NAME = 'test_entry'
  28. MAX_ENTRIES = 10
  29. BIND_NAME = 'bind_entry'
  30. BIND_DN = 'cn=%s, %s' % (BIND_NAME, SUFFIX)
  31. BIND_PW = 'password'
  32. class TopologyMaster1Master2(object):
  33. def __init__(self, master1, master2):
  34. master1.open()
  35. self.master1 = master1
  36. master2.open()
  37. self.master2 = master2
  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 MASTER1 <-> Master2.
  43. '''
  44. global installation1_prefix
  45. global installation2_prefix
  46. # allocate master1 on a given deployement
  47. master1 = DirSrv(verbose=False)
  48. if installation1_prefix:
  49. args_instance[SER_DEPLOYED_DIR] = installation1_prefix
  50. # Args for the master1 instance
  51. args_instance[SER_HOST] = HOST_MASTER_1
  52. args_instance[SER_PORT] = PORT_MASTER_1
  53. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1
  54. args_master = args_instance.copy()
  55. master1.allocate(args_master)
  56. # allocate master1 on a given deployement
  57. master2 = DirSrv(verbose=False)
  58. if installation2_prefix:
  59. args_instance[SER_DEPLOYED_DIR] = installation2_prefix
  60. # Args for the consumer instance
  61. args_instance[SER_HOST] = HOST_MASTER_2
  62. args_instance[SER_PORT] = PORT_MASTER_2
  63. args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2
  64. args_master = args_instance.copy()
  65. master2.allocate(args_master)
  66. # Get the status of the instance
  67. instance_master1 = master1.exists()
  68. instance_master2 = master2.exists()
  69. # Remove all the instances
  70. if instance_master1:
  71. master1.delete()
  72. if instance_master2:
  73. master2.delete()
  74. # Create the instances
  75. master1.create()
  76. master1.open()
  77. master2.create()
  78. master2.open()
  79. #
  80. # Now prepare the Master-Consumer topology
  81. #
  82. # First Enable replication
  83. master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1)
  84. master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2)
  85. # Initialize the supplier->consumer
  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. repl_agreement = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties)
  92. if not repl_agreement:
  93. log.fatal("Fail to create a replica agreement")
  94. sys.exit(1)
  95. log.debug("%s created" % repl_agreement)
  96. properties = {RA_NAME: r'meTo_$host:$port',
  97. RA_BINDDN: defaultProperties[REPLICATION_BIND_DN],
  98. RA_BINDPW: defaultProperties[REPLICATION_BIND_PW],
  99. RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD],
  100. RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]}
  101. master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties)
  102. master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2)
  103. master1.waitForReplInit(repl_agreement)
  104. # Check replication is working fine
  105. if master1.testReplication(DEFAULT_SUFFIX, master2):
  106. log.info('Replication is working.')
  107. else:
  108. log.fatal('Replication is not working.')
  109. assert False
  110. def fin():
  111. master1.delete()
  112. master2.delete()
  113. request.addfinalizer(fin)
  114. # Here we have two instances master and consumer
  115. return TopologyMaster1Master2(master1, master2)
  116. def test_ticket47869_init(topology):
  117. """
  118. It adds an entry ('bind_entry') and 10 test entries
  119. It sets the anonymous aci
  120. """
  121. # enable acl error logging
  122. mod = [(ldap.MOD_REPLACE, 'nsslapd-errorlog-level', str(8192))] # REPL
  123. topology.master1.modify_s(DN_CONFIG, mod)
  124. topology.master2.modify_s(DN_CONFIG, mod)
  125. # entry used to bind with
  126. topology.master1.log.info("Add %s" % BIND_DN)
  127. topology.master1.add_s(Entry((BIND_DN, {
  128. 'objectclass': "top person".split(),
  129. 'sn': BIND_NAME,
  130. 'cn': BIND_NAME,
  131. 'userpassword': BIND_PW})))
  132. loop = 0
  133. ent = None
  134. while loop <= 10:
  135. try:
  136. ent = topology.master2.getEntry(BIND_DN, ldap.SCOPE_BASE, "(objectclass=*)")
  137. break
  138. except ldap.NO_SUCH_OBJECT:
  139. time.sleep(1)
  140. loop += 1
  141. if ent is None:
  142. assert False
  143. # keep anonymous ACI for use 'read-search' aci in SEARCH test
  144. ACI_ANONYMOUS = "(targetattr!=\"userPassword\")(version 3.0; acl \"Enable anonymous access\"; allow (read, search, compare) userdn=\"ldap:///anyone\";)"
  145. mod = [(ldap.MOD_REPLACE, 'aci', ACI_ANONYMOUS)]
  146. topology.master1.modify_s(SUFFIX, mod)
  147. topology.master2.modify_s(SUFFIX, mod)
  148. # add entries
  149. for cpt in range(MAX_ENTRIES):
  150. name = "%s%d" % (ENTRY_NAME, cpt)
  151. mydn = "cn=%s,%s" % (name, SUFFIX)
  152. topology.master1.add_s(Entry((mydn,
  153. {'objectclass': "top person".split(),
  154. 'sn': name,
  155. 'cn': name})))
  156. loop = 0
  157. ent = None
  158. while loop <= 10:
  159. try:
  160. ent = topology.master2.getEntry(mydn, ldap.SCOPE_BASE, "(objectclass=*)")
  161. break
  162. except ldap.NO_SUCH_OBJECT:
  163. time.sleep(1)
  164. loop += 1
  165. if ent is None:
  166. assert False
  167. def test_ticket47869_check(topology):
  168. '''
  169. On Master 1 and 2:
  170. Bind as Directory Manager.
  171. Search all specifying nscpEntryWsi in the attribute list.
  172. Check nscpEntryWsi is returned.
  173. On Master 1 and 2:
  174. Bind as Bind Entry.
  175. Search all specifying nscpEntryWsi in the attribute list.
  176. Check nscpEntryWsi is not returned.
  177. On Master 1 and 2:
  178. Bind as anonymous.
  179. Search all specifying nscpEntryWsi in the attribute list.
  180. Check nscpEntryWsi is not returned.
  181. '''
  182. topology.master1.log.info("\n\n######################### CHECK nscpentrywsi ######################\n")
  183. topology.master1.log.info("##### Master1: Bind as %s #####" % DN_DM)
  184. topology.master1.simple_bind_s(DN_DM, PASSWORD)
  185. topology.master1.log.info("Master1: Calling search_ext...")
  186. msgid = topology.master1.search_ext(SUFFIX, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nscpentrywsi'])
  187. nscpentrywsicnt = 0
  188. rtype, rdata, rmsgid = topology.master1.result2(msgid)
  189. topology.master1.log.info("%d results" % len(rdata))
  190. topology.master1.log.info("Results:")
  191. for dn, attrs in rdata:
  192. topology.master1.log.info("dn: %s" % dn)
  193. if 'nscpentrywsi' in attrs:
  194. nscpentrywsicnt += 1
  195. topology.master1.log.info("Master1: count of nscpentrywsi: %d" % nscpentrywsicnt)
  196. topology.master2.log.info("##### Master2: Bind as %s #####" % DN_DM)
  197. topology.master2.simple_bind_s(DN_DM, PASSWORD)
  198. topology.master2.log.info("Master2: Calling search_ext...")
  199. msgid = topology.master2.search_ext(SUFFIX, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nscpentrywsi'])
  200. nscpentrywsicnt = 0
  201. rtype, rdata, rmsgid = topology.master2.result2(msgid)
  202. topology.master2.log.info("%d results" % len(rdata))
  203. topology.master2.log.info("Results:")
  204. for dn, attrs in rdata:
  205. topology.master2.log.info("dn: %s" % dn)
  206. if 'nscpentrywsi' in attrs:
  207. nscpentrywsicnt += 1
  208. topology.master2.log.info("Master2: count of nscpentrywsi: %d" % nscpentrywsicnt)
  209. # bind as bind_entry
  210. topology.master1.log.info("##### Master1: Bind as %s #####" % BIND_DN)
  211. topology.master1.simple_bind_s(BIND_DN, BIND_PW)
  212. topology.master1.log.info("Master1: Calling search_ext...")
  213. msgid = topology.master1.search_ext(SUFFIX, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nscpentrywsi'])
  214. nscpentrywsicnt = 0
  215. rtype, rdata, rmsgid = topology.master1.result2(msgid)
  216. topology.master1.log.info("%d results" % len(rdata))
  217. for dn, attrs in rdata:
  218. if 'nscpentrywsi' in attrs:
  219. nscpentrywsicnt += 1
  220. assert nscpentrywsicnt == 0
  221. topology.master1.log.info("Master1: count of nscpentrywsi: %d" % nscpentrywsicnt)
  222. # bind as bind_entry
  223. topology.master2.log.info("##### Master2: Bind as %s #####" % BIND_DN)
  224. topology.master2.simple_bind_s(BIND_DN, BIND_PW)
  225. topology.master2.log.info("Master2: Calling search_ext...")
  226. msgid = topology.master2.search_ext(SUFFIX, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nscpentrywsi'])
  227. nscpentrywsicnt = 0
  228. rtype, rdata, rmsgid = topology.master2.result2(msgid)
  229. topology.master2.log.info("%d results" % len(rdata))
  230. for dn, attrs in rdata:
  231. if 'nscpentrywsi' in attrs:
  232. nscpentrywsicnt += 1
  233. assert nscpentrywsicnt == 0
  234. topology.master2.log.info("Master2: count of nscpentrywsi: %d" % nscpentrywsicnt)
  235. # bind as anonymous
  236. topology.master1.log.info("##### Master1: Bind as anonymous #####")
  237. topology.master1.simple_bind_s("", "")
  238. topology.master1.log.info("Master1: Calling search_ext...")
  239. msgid = topology.master1.search_ext(SUFFIX, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nscpentrywsi'])
  240. nscpentrywsicnt = 0
  241. rtype, rdata, rmsgid = topology.master1.result2(msgid)
  242. topology.master1.log.info("%d results" % len(rdata))
  243. for dn, attrs in rdata:
  244. if 'nscpentrywsi' in attrs:
  245. nscpentrywsicnt += 1
  246. assert nscpentrywsicnt == 0
  247. topology.master1.log.info("Master1: count of nscpentrywsi: %d" % nscpentrywsicnt)
  248. # bind as bind_entry
  249. topology.master2.log.info("##### Master2: Bind as anonymous #####")
  250. topology.master2.simple_bind_s("", "")
  251. topology.master2.log.info("Master2: Calling search_ext...")
  252. msgid = topology.master2.search_ext(SUFFIX, ldap.SCOPE_SUBTREE, 'objectclass=*', ['nscpentrywsi'])
  253. nscpentrywsicnt = 0
  254. rtype, rdata, rmsgid = topology.master2.result2(msgid)
  255. topology.master2.log.info("%d results" % len(rdata))
  256. for dn, attrs in rdata:
  257. if 'nscpentrywsi' in attrs:
  258. nscpentrywsicnt += 1
  259. assert nscpentrywsicnt == 0
  260. topology.master2.log.info("Master2: count of nscpentrywsi: %d" % nscpentrywsicnt)
  261. topology.master1.log.info("##### ticket47869 was successfully verified. #####")
  262. def test_ticket47869_final(topology):
  263. log.info('Testcase PASSED')
  264. def run_isolated():
  265. '''
  266. run_isolated is used to run these test cases independently of a test scheduler (xunit, py.test..)
  267. To run isolated without py.test, you need to
  268. - edit this file and comment '@pytest.fixture' line before 'topology' function.
  269. - set the installation prefix
  270. - run this program
  271. '''
  272. global installation1_prefix
  273. global installation2_prefix
  274. installation1_prefix = None
  275. installation2_prefix = None
  276. topo = topology(True)
  277. test_ticket47869_init(topo)
  278. test_ticket47869_check(topo)
  279. test_ticket47869_final(topo)
  280. if __name__ == '__main__':
  281. run_isolated()