ticket47869MMR_test.py 12 KB

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