conflict_resolve_test.py 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2020 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 time
  10. import logging
  11. import ldap
  12. import pytest
  13. import re
  14. from itertools import permutations
  15. from lib389._constants import *
  16. from lib389.idm.nscontainer import nsContainers
  17. from lib389.idm.user import UserAccounts, UserAccount
  18. from lib389.idm.group import Groups
  19. from lib389.idm.organizationalunit import OrganizationalUnits
  20. from lib389.replica import ReplicationManager
  21. from lib389.agreement import Agreements
  22. from lib389.plugins import MemberOfPlugin
  23. pytestmark = pytest.mark.tier1
  24. DEBUGGING = os.getenv("DEBUGGING", default=False)
  25. if DEBUGGING:
  26. logging.getLogger(__name__).setLevel(logging.DEBUG)
  27. else:
  28. logging.getLogger(__name__).setLevel(logging.INFO)
  29. log = logging.getLogger(__name__)
  30. def _create_user(users, user_num, group_num=2000, sleep=False):
  31. """Creates user entry"""
  32. user = users.create_test_user(user_num, group_num)
  33. if sleep:
  34. time.sleep(1)
  35. return user
  36. def _rename_user(users, user_num, new_num, sleep=False):
  37. """Rename user entry"""
  38. assert user_num != new_num, "New user number should not be the same as the old one"
  39. user = users.get('test_user_{}'.format(user_num))
  40. user.rename('uid=test_user_{}'.format(new_num))
  41. if sleep:
  42. time.sleep(1)
  43. def _modify_user(users, user_num, sleep=False):
  44. """Modify user entry"""
  45. user = users.get('test_user_{}'.format(user_num))
  46. user.replace("homeDirectory", "/home/test_user0{}".format(user_num))
  47. if sleep:
  48. time.sleep(1)
  49. time.sleep(1)
  50. def _delete_user(users, user_num, sleep=False):
  51. """Delete user entry"""
  52. user = users.get('test_user_{}'.format(user_num))
  53. user.delete()
  54. if sleep:
  55. time.sleep(1)
  56. time.sleep(1)
  57. def _create_group(groups, num, member, sleep=False):
  58. """Creates group entry"""
  59. group_props = {'cn': 'test_group_{}'.format(num),
  60. 'member': member}
  61. group = groups.create(properties=group_props)
  62. if sleep:
  63. time.sleep(1)
  64. return group
  65. def _delete_group(groups, num, sleep=False):
  66. """Delete group entry"""
  67. group = groups.get('test_group_{}'.format(num))
  68. group.delete()
  69. if sleep:
  70. time.sleep(1)
  71. def _create_container(inst, dn, name, sleep=False):
  72. """Creates container entry"""
  73. conts = nsContainers(inst, dn)
  74. cont = conts.create(properties={'cn': name})
  75. if sleep:
  76. time.sleep(1)
  77. return cont
  78. def _delete_container(cont, sleep=False):
  79. """Deletes container entry"""
  80. cont.delete()
  81. if sleep:
  82. time.sleep(1)
  83. def _test_base(topology):
  84. """Add test container for entries, enable plugin logging,
  85. audit log, error log for replica and access log for internal
  86. """
  87. M1 = topology.ms["master1"]
  88. conts = nsContainers(M1, SUFFIX)
  89. base_m2 = conts.ensure_state(properties={'cn': 'test_container'})
  90. for inst in topology:
  91. inst.config.loglevel([ErrorLog.DEFAULT, ErrorLog.REPLICA], service='error')
  92. inst.config.loglevel([AccessLog.DEFAULT, AccessLog.INTERNAL], service='access')
  93. inst.config.set('nsslapd-plugin-logging', 'on')
  94. inst.config.enable_log('audit')
  95. inst.restart()
  96. return base_m2
  97. def _delete_test_base(inst, base_m2_dn):
  98. """Delete test container with entries and entry conflicts"""
  99. ents = inst.search_s(base_m2_dn, ldap.SCOPE_SUBTREE, filterstr="(|(objectclass=*)(objectclass=ldapsubentry))")
  100. for ent in sorted(ents, key=lambda e: len(e.dn), reverse=True):
  101. log.debug("Delete entry children {}".format(ent.dn))
  102. try:
  103. inst.delete_ext_s(ent.dn)
  104. except ldap.NO_SUCH_OBJECT: # For the case with objectclass: glue entries
  105. pass
  106. @pytest.fixture
  107. def base_m2(topology_m2, request):
  108. tb = _test_base(topology_m2)
  109. def fin():
  110. if not DEBUGGING:
  111. _delete_test_base(topology_m2.ms["master1"], tb.dn)
  112. request.addfinalizer(fin)
  113. return tb
  114. @pytest.fixture
  115. def base_m3(topology_m3, request):
  116. tb = _test_base(topology_m3)
  117. def fin():
  118. if not DEBUGGING:
  119. _delete_test_base(topology_m3.ms["master1"], tb.dn)
  120. request.addfinalizer(fin)
  121. return tb
  122. class TestTwoMasters:
  123. def test_add_modrdn(self, topology_m2, base_m2):
  124. """Check that conflict properly resolved for create - modrdn operations
  125. :id: 77f09b18-03d1-45da-940b-1ad2c2908ebb
  126. :setup: Two master replication, test container for entries, enable plugin logging,
  127. audit log, error log for replica and access log for internal
  128. :steps:
  129. 1. Add five users to m1 and wait for replication to happen
  130. 2. Pause replication
  131. 3. Create an entry on m1 and m2
  132. 4. Create an entry on m1 and rename on m2
  133. 5. Rename an entry on m1 and create on m2
  134. 6. Rename an entry on m1 and rename on m2
  135. 7. Rename an entry on m1 and rename on m2. Use different entries
  136. but rename them to the same entry
  137. 8. Resume replication
  138. 9. Check that the entries on both masters are the same and replication is working
  139. :expectedresults:
  140. 1. It should pass
  141. 2. It should pass
  142. 3. It should pass
  143. 4. It should pass
  144. 5. It should pass
  145. 6. It should pass
  146. 7. It should pass
  147. 8. It should pass
  148. """
  149. M1 = topology_m2.ms["master1"]
  150. M2 = topology_m2.ms["master2"]
  151. test_users_m1 = UserAccounts(M1, base_m2.dn, rdn=None)
  152. test_users_m2 = UserAccounts(M2, base_m2.dn, rdn=None)
  153. repl = ReplicationManager(SUFFIX)
  154. for user_num in range(1000, 1005):
  155. _create_user(test_users_m1, user_num)
  156. repl.test_replication(M1, M2)
  157. topology_m2.pause_all_replicas()
  158. log.info("Test create - modrdn")
  159. user_num += 1
  160. _create_user(test_users_m1, user_num, sleep=True)
  161. _create_user(test_users_m2, user_num, sleep=True)
  162. user_num += 1
  163. _create_user(test_users_m1, user_num, sleep=True)
  164. _rename_user(test_users_m2, 1000, user_num, sleep=True)
  165. user_num += 1
  166. _rename_user(test_users_m1, 1001, user_num, sleep=True)
  167. _create_user(test_users_m2, user_num, sleep=True)
  168. user_num += 1
  169. _rename_user(test_users_m1, 1002, user_num, sleep=True)
  170. _rename_user(test_users_m2, 1002, user_num, sleep=True)
  171. user_num += 1
  172. _rename_user(test_users_m1, 1003, user_num, sleep=True)
  173. _rename_user(test_users_m2, 1004, user_num)
  174. topology_m2.resume_all_replicas()
  175. repl.test_replication_topology(topology_m2)
  176. user_dns_m1 = [user.dn for user in test_users_m1.list()]
  177. user_dns_m2 = [user.dn for user in test_users_m2.list()]
  178. assert set(user_dns_m1) == set(user_dns_m2)
  179. def test_complex_add_modify_modrdn_delete(self, topology_m2, base_m2):
  180. """Check that conflict properly resolved for complex operations
  181. which involve add, modify, modrdn and delete
  182. :id: 77f09b18-03d1-45da-940b-1ad2c2908eb1
  183. :setup: Two master replication, test container for entries, enable plugin logging,
  184. audit log, error log for replica and access log for internal
  185. :steps:
  186. 1. Add ten users to m1 and wait for replication to happen
  187. 2. Pause replication
  188. 3. Test add-del on m1 and add on m2
  189. 4. Test add-mod on m1 and add on m2
  190. 5. Test add-modrdn on m1 and add on m2
  191. 6. Test multiple add, modrdn
  192. 7. Test Add-del on both masters
  193. 8. Test modrdn-modrdn
  194. 9. Test modrdn-del
  195. 10. Resume replication
  196. 11. Check that the entries on both masters are the same and replication is working
  197. :expectedresults:
  198. 1. It should pass
  199. 2. It should pass
  200. 3. It should pass
  201. 4. It should pass
  202. 5. It should pass
  203. 6. It should pass
  204. 7. It should pass
  205. 8. It should pass
  206. 9. It should pass
  207. 10. It should pass
  208. 11. It should pass
  209. """
  210. M1 = topology_m2.ms["master1"]
  211. M2 = topology_m2.ms["master2"]
  212. test_users_m1 = UserAccounts(M1, base_m2.dn, rdn=None)
  213. test_users_m2 = UserAccounts(M2, base_m2.dn, rdn=None)
  214. repl = ReplicationManager(SUFFIX)
  215. for user_num in range(1100, 1110):
  216. _create_user(test_users_m1, user_num)
  217. repl.test_replication(M1, M2)
  218. topology_m2.pause_all_replicas()
  219. log.info("Test add-del on M1 and add on M2")
  220. user_num += 1
  221. _create_user(test_users_m1, user_num)
  222. _delete_user(test_users_m1, user_num, sleep=True)
  223. _create_user(test_users_m2, user_num, sleep=True)
  224. user_num += 1
  225. _create_user(test_users_m1, user_num, sleep=True)
  226. _create_user(test_users_m2, user_num, sleep=True)
  227. _delete_user(test_users_m1, user_num, sleep=True)
  228. user_num += 1
  229. _create_user(test_users_m2, user_num, sleep=True)
  230. _create_user(test_users_m1, user_num)
  231. _delete_user(test_users_m1, user_num)
  232. log.info("Test add-mod on M1 and add on M2")
  233. user_num += 1
  234. _create_user(test_users_m1, user_num)
  235. _modify_user(test_users_m1, user_num, sleep=True)
  236. _create_user(test_users_m2, user_num, sleep=True)
  237. user_num += 1
  238. _create_user(test_users_m1, user_num, sleep=True)
  239. _create_user(test_users_m2, user_num, sleep=True)
  240. _modify_user(test_users_m1, user_num, sleep=True)
  241. user_num += 1
  242. _create_user(test_users_m2, user_num, sleep=True)
  243. _create_user(test_users_m1, user_num)
  244. _modify_user(test_users_m1, user_num)
  245. log.info("Test add-modrdn on M1 and add on M2")
  246. user_num += 1
  247. _create_user(test_users_m1, user_num)
  248. _rename_user(test_users_m1, user_num, user_num+20, sleep=True)
  249. _create_user(test_users_m2, user_num, sleep=True)
  250. user_num += 1
  251. _create_user(test_users_m1, user_num, sleep=True)
  252. _create_user(test_users_m2, user_num, sleep=True)
  253. _rename_user(test_users_m1, user_num, user_num+20, sleep=True)
  254. user_num += 1
  255. _create_user(test_users_m2, user_num, sleep=True)
  256. _create_user(test_users_m1, user_num)
  257. _rename_user(test_users_m1, user_num, user_num+20)
  258. log.info("Test multiple add, modrdn")
  259. user_num += 1
  260. _create_user(test_users_m1, user_num, sleep=True)
  261. _create_user(test_users_m2, user_num, sleep=True)
  262. _rename_user(test_users_m1, user_num, user_num+20)
  263. _create_user(test_users_m1, user_num, sleep=True)
  264. _modify_user(test_users_m2, user_num, sleep=True)
  265. log.info("Add - del on both masters")
  266. user_num += 1
  267. _create_user(test_users_m1, user_num)
  268. _delete_user(test_users_m1, user_num, sleep=True)
  269. _create_user(test_users_m2, user_num)
  270. _delete_user(test_users_m2, user_num, sleep=True)
  271. log.info("Test modrdn - modrdn")
  272. user_num += 1
  273. _rename_user(test_users_m1, 1109, 1129, sleep=True)
  274. _rename_user(test_users_m2, 1109, 1129, sleep=True)
  275. log.info("Test modrdn - del")
  276. user_num += 1
  277. _rename_user(test_users_m1, 1100, 1120, sleep=True)
  278. _delete_user(test_users_m2, 1100)
  279. user_num += 1
  280. _delete_user(test_users_m2, 1101, sleep=True)
  281. _rename_user(test_users_m1, 1101, 1121)
  282. topology_m2.resume_all_replicas()
  283. repl.test_replication_topology(topology_m2)
  284. time.sleep(30)
  285. user_dns_m1 = [user.dn for user in test_users_m1.list()]
  286. user_dns_m2 = [user.dn for user in test_users_m2.list()]
  287. assert set(user_dns_m1) == set(user_dns_m2)
  288. def test_memberof_groups(self, topology_m2, base_m2):
  289. """Check that conflict properly resolved for operations
  290. with memberOf and groups
  291. :id: 77f09b18-03d1-45da-940b-1ad2c2908eb3
  292. :setup: Two master replication, test container for entries, enable plugin logging,
  293. audit log, error log for replica and access log for internal
  294. :steps:
  295. 1. Enable memberOf plugin
  296. 2. Add 30 users to m1 and wait for replication to happen
  297. 3. Pause replication
  298. 4. Create a group on m1 and m2
  299. 5. Create a group on m1 and m2, delete from m1
  300. 6. Create a group on m1, delete from m1, and create on m2,
  301. 7. Create a group on m2 and m1, delete from m1
  302. 8. Create two different groups on m2
  303. 9. Resume replication
  304. 10. Check that the entries on both masters are the same and replication is working
  305. :expectedresults:
  306. 1. It should pass
  307. 2. It should pass
  308. 3. It should pass
  309. 4. It should pass
  310. 5. It should pass
  311. 6. It should pass
  312. 7. It should pass
  313. 8. It should pass
  314. 9. It should pass
  315. 10. It should pass
  316. """
  317. pytest.xfail("Issue 49591 - work in progress")
  318. M1 = topology_m2.ms["master1"]
  319. M2 = topology_m2.ms["master2"]
  320. test_users_m1 = UserAccounts(M1, base_m2.dn, rdn=None)
  321. test_groups_m1 = Groups(M1, base_m2.dn, rdn=None)
  322. test_groups_m2 = Groups(M2, base_m2.dn, rdn=None)
  323. repl = ReplicationManager(SUFFIX)
  324. for inst in topology_m2.ms.values():
  325. memberof = MemberOfPlugin(inst)
  326. memberof.enable()
  327. agmt = Agreements(inst).list()[0]
  328. agmt.replace_many(('nsDS5ReplicatedAttributeListTotal',
  329. '(objectclass=*) $ EXCLUDE '),
  330. ('nsDS5ReplicatedAttributeList',
  331. '(objectclass=*) $ EXCLUDE memberOf'))
  332. inst.restart()
  333. user_dns = []
  334. for user_num in range(10):
  335. user_trio = []
  336. for num in range(0, 30, 10):
  337. user = _create_user(test_users_m1, 1200 + user_num + num)
  338. user_trio.append(user.dn)
  339. user_dns.append(user_trio)
  340. repl.test_replication(M1, M2)
  341. topology_m2.pause_all_replicas()
  342. log.info("Check a simple conflict")
  343. group_num = 0
  344. _create_group(test_groups_m1, group_num, user_dns[group_num], sleep=True)
  345. _create_group(test_groups_m2, group_num, user_dns[group_num], sleep=True)
  346. log.info("Check a add - del")
  347. group_num += 1
  348. _create_group(test_groups_m1, group_num, user_dns[group_num], sleep=True)
  349. _create_group(test_groups_m2, group_num, user_dns[group_num], sleep=True)
  350. _delete_group(test_groups_m1, group_num)
  351. group_num += 1
  352. _create_group(test_groups_m1, group_num, user_dns[group_num])
  353. _delete_group(test_groups_m1, group_num, sleep=True)
  354. _create_group(test_groups_m2, group_num, user_dns[group_num])
  355. group_num += 1
  356. _create_group(test_groups_m2, group_num, user_dns[group_num], sleep=True)
  357. _create_group(test_groups_m1, group_num, user_dns[group_num])
  358. _delete_group(test_groups_m1, group_num, sleep=True)
  359. group_num += 1
  360. _create_group(test_groups_m2, group_num, user_dns[group_num])
  361. group_num += 1
  362. _create_group(test_groups_m2, group_num, user_dns[group_num])
  363. topology_m2.resume_all_replicas()
  364. repl.test_replication_topology(topology_m2)
  365. group_dns_m1 = [group.dn for group in test_groups_m1.list()]
  366. group_dns_m2 = [group.dn for group in test_groups_m2.list()]
  367. assert set(group_dns_m1) == set(group_dns_m2)
  368. def test_managed_entries(self, topology_m2):
  369. """Check that conflict properly resolved for operations
  370. with managed entries
  371. :id: 77f09b18-03d1-45da-940b-1ad2c2908eb4
  372. :setup: Two master replication, test container for entries, enable plugin logging,
  373. audit log, error log for replica and access log for internal
  374. :steps:
  375. 1. Create ou=managed_users and ou=managed_groups under test container
  376. 2. Configure managed entries plugin and add a template to test container
  377. 3. Add a user to m1 and wait for replication to happen
  378. 4. Pause replication
  379. 5. Create a user on m1 and m2 with a same group ID on both master
  380. 6. Create a user on m1 and m2 with a different group ID on both master
  381. 7. Resume replication
  382. 8. Check that the entries on both masters are the same and replication is working
  383. :expectedresults:
  384. 1. It should pass
  385. 2. It should pass
  386. 3. It should pass
  387. 4. It should pass
  388. 5. It should pass
  389. 6. It should pass
  390. 7. It should pass
  391. 8. It should pass
  392. """
  393. pytest.xfail("Issue 49591 - work in progress")
  394. M1 = topology_m2.ms["master1"]
  395. M2 = topology_m2.ms["master2"]
  396. repl = ReplicationManager(SUFFIX)
  397. ous = OrganizationalUnits(M1, DEFAULT_SUFFIX)
  398. ou_people = ous.create(properties={'ou': 'managed_people'})
  399. ou_groups = ous.create(properties={'ou': 'managed_groups'})
  400. test_users_m1 = UserAccounts(M1, DEFAULT_SUFFIX, rdn='ou={}'.format(ou_people.rdn))
  401. test_users_m2 = UserAccounts(M2, DEFAULT_SUFFIX, rdn='ou={}'.format(ou_people.rdn))
  402. # TODO: Refactor ManagedPlugin class functionality (also add configs and templates)
  403. conts = nsContainers(M1, SUFFIX)
  404. template = conts.create(properties={
  405. 'objectclass': 'top mepTemplateEntry extensibleObject'.split(),
  406. 'cn': 'MEP Template',
  407. 'mepRDNAttr': 'cn',
  408. 'mepStaticAttr': ['objectclass: posixGroup', 'objectclass: extensibleObject'],
  409. 'mepMappedAttr': ['cn: $uid', 'uid: $cn', 'gidNumber: $uidNumber']
  410. })
  411. repl.test_replication(M1, M2)
  412. for inst in topology_m2.ms.values():
  413. conts = nsContainers(inst, "cn={},{}".format(PLUGIN_MANAGED_ENTRY, DN_PLUGIN))
  414. conts.create(properties={'objectclass': 'top extensibleObject'.split(),
  415. 'cn': 'config',
  416. 'originScope': ou_people.dn,
  417. 'originFilter': 'objectclass=posixAccount',
  418. 'managedBase': ou_groups.dn,
  419. 'managedTemplate': template.dn})
  420. inst.restart()
  421. _create_user(test_users_m1, 1, 1)
  422. topology_m2.pause_all_replicas()
  423. _create_user(test_users_m1, 2, 2, sleep=True)
  424. _create_user(test_users_m2, 2, 2, sleep=True)
  425. _create_user(test_users_m1, 3, 3, sleep=True)
  426. _create_user(test_users_m2, 3, 33)
  427. topology_m2.resume_all_replicas()
  428. repl.test_replication_topology(topology_m2)
  429. user_dns_m1 = [user.dn for user in test_users_m1.list()]
  430. user_dns_m2 = [user.dn for user in test_users_m2.list()]
  431. assert set(user_dns_m1) == set(user_dns_m2)
  432. def test_nested_entries_with_children(self, topology_m2, base_m2):
  433. """Check that conflict properly resolved for operations
  434. with nested entries with children
  435. :id: 77f09b18-03d1-45da-940b-1ad2c2908eb5
  436. :setup: Two master replication, test container for entries, enable plugin logging,
  437. audit log, error log for replica and access log for internal
  438. :steps:
  439. 1. Add 15 containers to m1 and wait for replication to happen
  440. 2. Pause replication
  441. 3. Create parent-child on master2 and master1
  442. 4. Create parent-child on master1 and master2
  443. 5. Create parent-child on master1 and master2 different child rdn
  444. 6. Create parent-child on master1 and delete parent on master2
  445. 7. Create parent on master1, delete it and parent-child on master2, delete them
  446. 8. Create parent on master1, delete it and parent-two children on master2
  447. 9. Create parent-two children on master1 and parent-child on master2, delete them
  448. 10. Create three subsets inside existing container entry, applying only part of changes on m2
  449. 11. Create more combinations of the subset with parent-child on m1 and parent on m2
  450. 12. Delete container on m1, modify user1 on m1, create parent on m2 and modify user2 on m2
  451. 13. Resume replication
  452. 14. Check that the entries on both masters are the same and replication is working
  453. :expectedresults:
  454. 1. It should pass
  455. 2. It should pass
  456. 3. It should pass
  457. 4. It should pass
  458. 5. It should pass
  459. 6. It should pass
  460. 7. It should pass
  461. 8. It should pass
  462. 9. It should pass
  463. 10. It should pass
  464. 11. It should pass
  465. 12. It should pass
  466. 13. It should pass
  467. 14. It should pass
  468. """
  469. pytest.xfail("Issue 49591 - work in progress")
  470. M1 = topology_m2.ms["master1"]
  471. M2 = topology_m2.ms["master2"]
  472. repl = ReplicationManager(SUFFIX)
  473. test_users_m1 = UserAccounts(M1, base_m2.dn, rdn=None)
  474. test_users_m2 = UserAccounts(M2, base_m2.dn, rdn=None)
  475. _create_user(test_users_m1, 4000)
  476. _create_user(test_users_m1, 4001)
  477. cont_list = []
  478. for num in range(15):
  479. cont = _create_container(M1, base_m2.dn, 'sub{}'.format(num))
  480. cont_list.append(cont)
  481. repl.test_replication(M1, M2)
  482. topology_m2.pause_all_replicas()
  483. log.info("Create parent-child on master2 and master1")
  484. _create_container(M2, base_m2.dn, 'p0', sleep=True)
  485. cont_p = _create_container(M1, base_m2.dn, 'p0', sleep=True)
  486. _create_container(M1, cont_p.dn, 'c0', sleep=True)
  487. _create_container(M2, cont_p.dn, 'c0', sleep=True)
  488. log.info("Create parent-child on master1 and master2")
  489. cont_p = _create_container(M1, base_m2.dn, 'p1', sleep=True)
  490. _create_container(M2, base_m2.dn, 'p1', sleep=True)
  491. _create_container(M1, cont_p.dn, 'c1', sleep=True)
  492. _create_container(M2, cont_p.dn, 'c1', sleep=True)
  493. log.info("Create parent-child on master1 and master2 different child rdn")
  494. cont_p = _create_container(M1, base_m2.dn, 'p2', sleep=True)
  495. _create_container(M2, base_m2.dn, 'p2', sleep=True)
  496. _create_container(M1, cont_p.dn, 'c2', sleep=True)
  497. _create_container(M2, cont_p.dn, 'c3', sleep=True)
  498. log.info("Create parent-child on master1 and delete parent on master2")
  499. cont_num = 0
  500. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0', sleep=True)
  501. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0', sleep=True)
  502. _create_container(M1, cont_p_m1.dn, 'c0', sleep=True)
  503. _delete_container(cont_p_m2)
  504. cont_num += 1
  505. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0', sleep=True)
  506. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  507. _create_container(M1, cont_p_m1.dn, 'c0', sleep=True)
  508. _delete_container(cont_p_m2, sleep=True)
  509. log.info("Create parent on master1, delete it and parent-child on master2, delete them")
  510. cont_num += 1
  511. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  512. _delete_container(cont_p_m1, sleep=True)
  513. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0')
  514. cont_c_m2 = _create_container(M2, cont_p_m2.dn, 'c0')
  515. _delete_container(cont_c_m2)
  516. _delete_container(cont_p_m2)
  517. cont_num += 1
  518. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0')
  519. cont_c_m2 = _create_container(M2, cont_p_m2.dn, 'c0')
  520. _delete_container(cont_c_m2)
  521. _delete_container(cont_p_m2, sleep=True)
  522. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  523. _delete_container(cont_p_m1)
  524. log.info("Create parent on master1, delete it and parent-two children on master2")
  525. cont_num += 1
  526. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  527. _delete_container(cont_p_m1, sleep=True)
  528. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0')
  529. _create_container(M2, cont_p_m2.dn, 'c0')
  530. _create_container(M2, cont_p_m2.dn, 'c1')
  531. cont_num += 1
  532. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0')
  533. _create_container(M2, cont_p_m2.dn, 'c0')
  534. _create_container(M2, cont_p_m2.dn, 'c1', sleep=True)
  535. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  536. _delete_container(cont_p_m1, sleep=True)
  537. log.info("Create parent-two children on master1 and parent-child on master2, delete them")
  538. cont_num += 1
  539. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0')
  540. cont_c_m2 = _create_container(M2, cont_p_m2.dn, 'c0')
  541. _delete_container(cont_c_m2)
  542. _delete_container(cont_p_m2, sleep=True)
  543. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  544. _create_container(M1, cont_p_m1.dn, 'c0')
  545. _create_container(M1, cont_p_m1.dn, 'c1')
  546. cont_num += 1
  547. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  548. _create_container(M1, cont_p_m1.dn, 'c0')
  549. _create_container(M1, cont_p_m1.dn, 'c1', sleep=True)
  550. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0')
  551. cont_c_m2 = _create_container(M2, cont_p_m2.dn, 'c0')
  552. _delete_container(cont_c_m2)
  553. _delete_container(cont_p_m2, sleep=True)
  554. log.info("Create three subsets inside existing container entry, applying only part of changes on m2")
  555. cont_num += 1
  556. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  557. _create_container(M1, cont_p_m1.dn, 'c0')
  558. _create_container(M1, cont_p_m1.dn, 'c1', sleep=True)
  559. _create_container(M2, cont_list[cont_num].dn, 'p0', sleep=True)
  560. cont_num += 1
  561. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  562. _create_container(M1, cont_p_m1.dn, 'c0')
  563. _create_container(M1, cont_p_m1.dn, 'c1', sleep=True)
  564. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0')
  565. _create_container(M2, cont_p_m2.dn, 'c0', sleep=True)
  566. cont_num += 1
  567. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0')
  568. _create_container(M1, cont_p_m1.dn, 'c0')
  569. _create_container(M1, cont_p_m1.dn, 'c1', sleep=True)
  570. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0')
  571. cont_c_m2 = _create_container(M2, cont_p_m2.dn, 'c0')
  572. _delete_container(cont_c_m2, sleep=True)
  573. log.info("Create more combinations of the subset with parent-child on m1 and parent on m2")
  574. cont_num += 1
  575. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0', sleep=True)
  576. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0', sleep=True)
  577. _delete_container(cont_p_m1, sleep=True)
  578. cont_c_m2 = _create_container(M2, cont_p_m2.dn, 'c0')
  579. _delete_container(cont_c_m2)
  580. _delete_container(cont_p_m2, sleep=True)
  581. cont_num += 1
  582. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0', sleep=True)
  583. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0', sleep=True)
  584. _delete_container(cont_p_m1, sleep=True)
  585. _create_container(M2, cont_p_m2.dn, 'c0', sleep=True)
  586. cont_num += 1
  587. cont_p_m1 = _create_container(M1, cont_list[cont_num].dn, 'p0', sleep=True)
  588. cont_p_m2 = _create_container(M2, cont_list[cont_num].dn, 'p0', sleep=True)
  589. cont_c_m1 = _create_container(M1, cont_p_m1.dn, 'c0', sleep=True)
  590. _create_container(M2, cont_p_m2.dn, 'c0', sleep=True)
  591. _delete_container(cont_c_m1, sleep=True)
  592. _create_container(M2, cont_p_m2.dn, 'c1', sleep=True)
  593. _delete_container(cont_p_m1, sleep=True)
  594. log.info("Delete container on m1, modify user1 on m1, create parent on m2 and modify user2 on m2")
  595. cont_num += 1
  596. _delete_container(cont_list[cont_num])
  597. _modify_user(test_users_m1, 4000, sleep=True)
  598. _create_container(M2, cont_list[cont_num].dn, 'p0')
  599. _modify_user(test_users_m2, 4001)
  600. topology_m2.resume_all_replicas()
  601. repl.test_replication_topology(topology_m2, timeout=60)
  602. conts_dns = {}
  603. for num in range(1, 3):
  604. inst = topology_m2.ms["master{}".format(num)]
  605. conts_dns[inst.serverid] = []
  606. conts = nsContainers(inst, base_m2.dn)
  607. for cont in conts.list():
  608. conts_p = nsContainers(inst, cont.dn)
  609. for cont_p in conts_p.list():
  610. conts_c = nsContainers(inst, cont_p.dn)
  611. conts_dns[inst.serverid].extend([cont_c.dn for cont_c in conts_c.list()])
  612. conts_dns[inst.serverid].extend([cont_p.dn for cont_p in conts_p.list()])
  613. conts_dns[inst.serverid].extend([cont.dn for cont in conts.list()])
  614. assert set(conts_dns[M1.serverid]) == set(conts_dns[M2.serverid])
  615. user_dns_m1 = [user.dn for user in test_users_m1.list()]
  616. user_dns_m2 = [user.dn for user in test_users_m2.list()]
  617. assert set(user_dns_m1) == set(user_dns_m2)
  618. def test_conflict_attribute_multi_valued(self, topology_m2, base_m2):
  619. """A RDN attribute being multi-valued, checks that after several operations
  620. MODRDN and MOD_REPL its RDN values are the same on both servers
  621. :id: 225b3522-8ed7-4256-96f9-5fab9b7044a5
  622. :setup: Two master replication,
  623. audit log, error log for replica and access log for internal
  624. :steps:
  625. 1. Create a test entry uid=user_test_1000,...
  626. 2. Pause all replication agreements
  627. 3. On M1 rename it into uid=foo1,...
  628. 4. On M2 rename it into uid=foo2,...
  629. 5. On M1 MOD_REPL uid:foo1
  630. 6. Resume all replication agreements
  631. 7. Check that entry on M1 has uid=foo1, foo2
  632. 8. Check that entry on M2 has uid=foo1, foo2
  633. 9. Check that entry on M1 and M2 has the same uid values
  634. :expectedresults:
  635. 1. It should pass
  636. 2. It should pass
  637. 3. It should pass
  638. 4. It should pass
  639. 5. It should pass
  640. 6. It should pass
  641. 7. It should pass
  642. 8. It should pass
  643. 9. It should pass
  644. """
  645. M1 = topology_m2.ms["master1"]
  646. M2 = topology_m2.ms["master2"]
  647. # add a test user
  648. test_users_m1 = UserAccounts(M1, base_m2.dn, rdn=None)
  649. user_1 = test_users_m1.create_test_user(uid=1000)
  650. test_users_m2 = UserAccount(M2, user_1.dn)
  651. # Waiting fo the user to be replicated
  652. for i in range(0,4):
  653. time.sleep(1)
  654. if test_users_m2.exists():
  655. break
  656. assert(test_users_m2.exists())
  657. # Stop replication agreements
  658. topology_m2.pause_all_replicas()
  659. # On M1 rename test entry in uid=foo1
  660. original_dn = user_1.dn
  661. user_1.rename('uid=foo1')
  662. time.sleep(1)
  663. # On M2 rename test entry in uid=foo2
  664. M2.rename_s(original_dn, 'uid=foo2')
  665. time.sleep(2)
  666. # on M1 MOD_REPL uid into foo1
  667. user_1.replace('uid', 'foo1')
  668. # resume replication agreements
  669. topology_m2.resume_all_replicas()
  670. time.sleep(5)
  671. # check that on M1, the entry 'uid' has two values 'foo1' and 'foo2'
  672. final_dn = re.sub('^.*1000,', 'uid=foo2,', original_dn)
  673. final_user_m1 = UserAccount(M1, final_dn)
  674. for val in final_user_m1.get_attr_vals_utf8('uid'):
  675. log.info("Check %s is on M1" % val)
  676. assert(val in ['foo1', 'foo2'])
  677. # check that on M2, the entry 'uid' has two values 'foo1' and 'foo2'
  678. final_user_m2 = UserAccount(M2, final_dn)
  679. for val in final_user_m2.get_attr_vals_utf8('uid'):
  680. log.info("Check %s is on M1" % val)
  681. assert(val in ['foo1', 'foo2'])
  682. # check that the entry have the same uid values
  683. for val in final_user_m1.get_attr_vals_utf8('uid'):
  684. log.info("Check M1.uid %s is also on M2" % val)
  685. assert(val in final_user_m2.get_attr_vals_utf8('uid'))
  686. for val in final_user_m2.get_attr_vals_utf8('uid'):
  687. log.info("Check M2.uid %s is also on M1" % val)
  688. assert(val in final_user_m1.get_attr_vals_utf8('uid'))
  689. def test_conflict_attribute_single_valued(self, topology_m2, base_m2):
  690. """A RDN attribute being signle-valued, checks that after several operations
  691. MODRDN and MOD_REPL its RDN values are the same on both servers
  692. :id: c38ae613-5d1e-47cf-b051-c7284e64b817
  693. :setup: Two master replication, test container for entries, enable plugin logging,
  694. audit log, error log for replica and access log for internal
  695. :steps:
  696. 1. Create a test entry uid=user_test_1000,...
  697. 2. Pause all replication agreements
  698. 3. On M1 rename it into employeenumber=foo1,...
  699. 4. On M2 rename it into employeenumber=foo2,...
  700. 5. On M1 MOD_REPL employeenumber:foo1
  701. 6. Resume all replication agreements
  702. 7. Check that entry on M1 has employeenumber=foo1
  703. 8. Check that entry on M2 has employeenumber=foo1
  704. 9. Check that entry on M1 and M2 has the same employeenumber values
  705. :expectedresults:
  706. 1. It should pass
  707. 2. It should pass
  708. 3. It should pass
  709. 4. It should pass
  710. 5. It should pass
  711. 6. It should pass
  712. 7. It should pass
  713. 8. It should pass
  714. 9. It should pass
  715. """
  716. M1 = topology_m2.ms["master1"]
  717. M2 = topology_m2.ms["master2"]
  718. # add a test user with a dummy 'uid' extra value because modrdn removes
  719. # uid that conflict with 'account' objectclass
  720. test_users_m1 = UserAccounts(M1, base_m2.dn, rdn=None)
  721. user_1 = test_users_m1.create_test_user(uid=1000)
  722. user_1.add('objectclass', 'extensibleobject')
  723. user_1.add('uid', 'dummy')
  724. test_users_m2 = UserAccount(M2, user_1.dn)
  725. # Waiting fo the user to be replicated
  726. for i in range(0,4):
  727. time.sleep(1)
  728. if test_users_m2.exists():
  729. break
  730. assert(test_users_m2.exists())
  731. # Stop replication agreements
  732. topology_m2.pause_all_replicas()
  733. # On M1 rename test entry in employeenumber=foo1
  734. original_dn = user_1.dn
  735. user_1.rename('employeenumber=foo1')
  736. time.sleep(1)
  737. # On M2 rename test entry in employeenumber=foo2
  738. M2.rename_s(original_dn, 'employeenumber=foo2')
  739. time.sleep(2)
  740. # on M1 MOD_REPL uid into foo1
  741. user_1.replace('employeenumber', 'foo1')
  742. # resume replication agreements
  743. topology_m2.resume_all_replicas()
  744. time.sleep(5)
  745. # check that on M1, the entry 'employeenumber' has value 'foo1'
  746. final_dn = re.sub('^.*1000,', 'employeenumber=foo2,', original_dn)
  747. final_user_m1 = UserAccount(M1, final_dn)
  748. for val in final_user_m1.get_attr_vals_utf8('employeenumber'):
  749. log.info("Check %s is on M1" % val)
  750. assert(val in ['foo1'])
  751. # check that on M2, the entry 'employeenumber' has values 'foo1'
  752. final_user_m2 = UserAccount(M2, final_dn)
  753. for val in final_user_m2.get_attr_vals_utf8('employeenumber'):
  754. log.info("Check %s is on M2" % val)
  755. assert(val in ['foo1'])
  756. # check that the entry have the same uid values
  757. for val in final_user_m1.get_attr_vals_utf8('employeenumber'):
  758. log.info("Check M1.uid %s is also on M2" % val)
  759. assert(val in final_user_m2.get_attr_vals_utf8('employeenumber'))
  760. for val in final_user_m2.get_attr_vals_utf8('employeenumber'):
  761. log.info("Check M2.uid %s is also on M1" % val)
  762. assert(val in final_user_m1.get_attr_vals_utf8('employeenumber'))
  763. class TestThreeMasters:
  764. def test_nested_entries(self, topology_m3, base_m3):
  765. """Check that conflict properly resolved for operations
  766. with nested entries with children
  767. :id: 77f09b18-03d1-45da-940b-1ad2c2908eb6
  768. :setup: Three master replication, test container for entries, enable plugin logging,
  769. audit log, error log for replica and access log for internal
  770. :steps:
  771. 1. Add 15 containers to m1 and wait for replication to happen
  772. 2. Pause replication
  773. 3. Create two child entries under each of two entries
  774. 4. Create three child entries under each of three entries
  775. 5. Create two parents on m1 and m2, then on m1 - create a child and delete one parent,
  776. on m2 - delete one parent and create a child
  777. 6. Test a few more parent-child combinations with three instances
  778. 7. Resume replication
  779. 8. Check that the entries on both masters are the same and replication is working
  780. :expectedresults:
  781. 1. It should pass
  782. 2. It should pass
  783. 3. It should pass
  784. 4. It should pass
  785. 5. It should pass
  786. 6. It should pass
  787. 7. It should pass
  788. 8. It should pass
  789. """
  790. pytest.xfail("Issue 49591 - work in progress")
  791. M1 = topology_m3.ms["master1"]
  792. M2 = topology_m3.ms["master2"]
  793. M3 = topology_m3.ms["master3"]
  794. repl = ReplicationManager(SUFFIX)
  795. cont_list = []
  796. for num in range(11):
  797. cont = _create_container(M1, base_m3.dn, 'sub{}'.format(num))
  798. cont_list.append(cont)
  799. repl.test_replication(M1, M2)
  800. repl.test_replication(M1, M3)
  801. topology_m3.pause_all_replicas()
  802. log.info("Create two child entries under each of two entries")
  803. cont_num = -1
  804. for num in range(2):
  805. cont_num += 1
  806. _create_container(M1, cont_list[cont_num].dn, 'p0', sleep=True)
  807. _create_container(M2, cont_list[cont_num].dn, 'p1', sleep=True)
  808. log.info("Create three child entries under each of three entries")
  809. for num in range(3):
  810. cont_num += 1
  811. _create_container(M1, cont_list[cont_num].dn, 'p0', sleep=True)
  812. _create_container(M2, cont_list[cont_num].dn, 'p1', sleep=True)
  813. _create_container(M3, cont_list[cont_num].dn, 'p2', sleep=True)
  814. log.info("Create two parents on m1 and m2, then on m1 - create a child and delete one parent,"
  815. "on m2 - delete one parent and create a child")
  816. for inst1, inst2 in ((M1, M2), (M2, M1)):
  817. cont_num += 1
  818. cont_p_m1_1 = _create_container(inst1, cont_list[cont_num].dn, 'p0')
  819. cont_p_m1_2 = _create_container(inst1, cont_list[cont_num].dn, 'p1', sleep=True)
  820. cont_p_m2_1 = _create_container(inst2, cont_list[cont_num].dn, 'p0')
  821. cont_p_m2_2 = _create_container(inst2, cont_list[cont_num].dn, 'p1', sleep=True)
  822. _create_container(inst1, cont_p_m1_1.dn, 'c0', sleep=True)
  823. _delete_container(cont_p_m2_1, sleep=True)
  824. _delete_container(cont_p_m1_2, sleep=True)
  825. _create_container(inst2, cont_p_m2_2.dn, 'c0', sleep=True)
  826. log.info("Test a few more parent-child combinations on three instances")
  827. for inst1, inst2, inst3 in ((M1, M2, M3), (M2, M1, M3), (M3, M1, M2)):
  828. cont_num += 1
  829. cont_p_m1 = _create_container(inst1, cont_list[cont_num].dn, 'p0')
  830. _delete_container(cont_p_m1, sleep=True)
  831. cont_p_m2 = _create_container(inst2, cont_list[cont_num].dn, 'p0')
  832. cont_c_m2 = _create_container(inst2, cont_p_m2.dn, 'c0')
  833. _delete_container(cont_c_m2)
  834. _delete_container(cont_p_m2, sleep=True)
  835. cont_p_m3 = _create_container(inst3, cont_list[cont_num].dn, 'p0')
  836. _create_container(inst3, cont_p_m3.dn, 'c0')
  837. _create_container(inst3, cont_p_m3.dn, 'c1', sleep=True)
  838. topology_m3.resume_all_replicas()
  839. repl.test_replication_topology(topology_m3)
  840. conts_dns = {}
  841. for num in range(1, 4):
  842. inst = topology_m3.ms["master{}".format(num)]
  843. conts_dns[inst.serverid] = []
  844. conts = nsContainers(inst, base_m3.dn)
  845. for cont in conts.list():
  846. conts_p = nsContainers(inst, cont.dn)
  847. for cont_p in conts_p.list():
  848. conts_c = nsContainers(inst, cont_p.dn)
  849. conts_dns[inst.serverid].extend([cont_c.dn for cont_c in conts_c.list()])
  850. conts_dns[inst.serverid].extend([cont_p.dn for cont_p in conts_p.list()])
  851. conts_dns[inst.serverid].extend([cont.dn for cont in conts.list()])
  852. for conts1, conts2 in permutations(conts_dns.values(), 2):
  853. assert set(conts1) == set(conts2)
  854. if __name__ == '__main__':
  855. # Run isolated
  856. # -s for DEBUG mode
  857. CURRENT_FILE = os.path.realpath(__file__)
  858. pytest.main("-s %s" % CURRENT_FILE)