ticket48294_test.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. import shutil
  16. from lib389 import DirSrv, Entry, tools
  17. from lib389 import DirSrvTools
  18. from lib389.tools import DirSrvTools
  19. from lib389._constants import *
  20. from lib389.properties import *
  21. log = logging.getLogger(__name__)
  22. LINKEDATTR_PLUGIN = 'cn=Linked Attributes,cn=plugins,cn=config'
  23. MANAGER_LINK = 'cn=Manager Link,' + LINKEDATTR_PLUGIN
  24. OU_PEOPLE = 'ou=People,' + DEFAULT_SUFFIX
  25. LINKTYPE = 'directReport'
  26. MANAGEDTYPE = 'manager'
  27. class TopologyStandalone(object):
  28. def __init__(self, standalone):
  29. standalone.open()
  30. self.standalone = standalone
  31. @pytest.fixture(scope="module")
  32. def topology(request):
  33. '''
  34. This fixture is used to standalone topology for the 'module'.
  35. '''
  36. standalone = DirSrv(verbose=False)
  37. # Args for the standalone instance
  38. args_instance[SER_HOST] = HOST_STANDALONE
  39. args_instance[SER_PORT] = PORT_STANDALONE
  40. args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
  41. args_standalone = args_instance.copy()
  42. standalone.allocate(args_standalone)
  43. # Get the status of the instance and restart it if it exists
  44. instance_standalone = standalone.exists()
  45. # Remove the instance
  46. if instance_standalone:
  47. standalone.delete()
  48. # Create the instance
  49. standalone.create()
  50. # Used to retrieve configuration information (dbdir, confdir...)
  51. standalone.open()
  52. def fin():
  53. standalone.delete()
  54. request.addfinalizer(fin)
  55. # Here we have standalone instance up and running
  56. return TopologyStandalone(standalone)
  57. def _header(topology, label):
  58. topology.standalone.log.info("###############################################")
  59. topology.standalone.log.info("####### %s" % label)
  60. topology.standalone.log.info("###############################################")
  61. def check_attr_val(topology, dn, attr, expected):
  62. try:
  63. centry = topology.standalone.search_s(dn, ldap.SCOPE_BASE, 'uid=*')
  64. if centry:
  65. val = centry[0].getValue(attr)
  66. if val.lower() == expected.lower():
  67. log.info('Value of %s is %s' % (attr, expected))
  68. else:
  69. log.info('Value of %s is not %s, but %s' % (attr, expected, val))
  70. assert False
  71. else:
  72. log.fatal('Failed to get %s' % dn)
  73. assert False
  74. except ldap.LDAPError as e:
  75. log.fatal('Failed to search ' + dn + ': ' + e.message['desc'])
  76. assert False
  77. def _modrdn_entry(topology=None, entry_dn=None, new_rdn=None, del_old=0, new_superior=None):
  78. assert topology is not None
  79. assert entry_dn is not None
  80. assert new_rdn is not None
  81. topology.standalone.log.info("\n\n######################### MODRDN %s ######################\n" % new_rdn)
  82. try:
  83. if new_superior:
  84. topology.standalone.rename_s(entry_dn, new_rdn, newsuperior=new_superior, delold=del_old)
  85. else:
  86. topology.standalone.rename_s(entry_dn, new_rdn, delold=del_old)
  87. except ldap.NO_SUCH_ATTRIBUTE:
  88. topology.standalone.log.info("accepted failure due to 47833: modrdn reports error.. but succeeds")
  89. attempt = 0
  90. if new_superior:
  91. dn = "%s,%s" % (new_rdn, new_superior)
  92. base = new_superior
  93. else:
  94. base = ','.join(entry_dn.split(",")[1:])
  95. dn = "%s, %s" % (new_rdn, base)
  96. myfilter = entry_dn.split(',')[0]
  97. while attempt < 10:
  98. try:
  99. ent = topology.standalone.getEntry(dn, ldap.SCOPE_BASE, myfilter)
  100. break
  101. except ldap.NO_SUCH_OBJECT:
  102. topology.standalone.log.info("Accept failure due to 47833: unable to find (base) a modrdn entry")
  103. attempt += 1
  104. time.sleep(1)
  105. if attempt == 10:
  106. ent = topology.standalone.getEntry(base, ldap.SCOPE_SUBTREE, myfilter)
  107. ent = topology.standalone.getEntry(dn, ldap.SCOPE_BASE, myfilter)
  108. def test_48294_init(topology):
  109. """
  110. Set up Linked Attribute
  111. """
  112. _header(topology, 'Testing Ticket 48294 - Linked Attributes plug-in - won\'t update links after MODRDN operation')
  113. log.info('Enable Dynamic plugins, and the linked Attrs plugin')
  114. try:
  115. topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-dynamic-plugins', 'on')])
  116. except ldap.LDAPError as e:
  117. ldap.fatal('Failed to enable dynamic plugin!' + e.message['desc'])
  118. assert False
  119. try:
  120. topology.standalone.plugins.enable(name=PLUGIN_LINKED_ATTRS)
  121. except ValueError as e:
  122. ldap.fatal('Failed to enable linked attributes plugin!' + e.message['desc'])
  123. assert False
  124. log.info('Add the plugin config entry')
  125. try:
  126. topology.standalone.add_s(Entry((MANAGER_LINK, {
  127. 'objectclass': 'top extensibleObject'.split(),
  128. 'cn': 'Manager Link',
  129. 'linkType': LINKTYPE,
  130. 'managedType': MANAGEDTYPE
  131. })))
  132. except ldap.LDAPError as e:
  133. log.fatal('Failed to add linked attr config entry: error ' + e.message['desc'])
  134. assert False
  135. log.info('Add 2 entries: manager1 and employee1')
  136. try:
  137. topology.standalone.add_s(Entry(('uid=manager1,%s' % OU_PEOPLE, {
  138. 'objectclass': 'top extensibleObject'.split(),
  139. 'uid': 'manager1'})))
  140. except ldap.LDAPError as e:
  141. log.fatal('Add manager1 failed: error ' + e.message['desc'])
  142. assert False
  143. try:
  144. topology.standalone.add_s(Entry(('uid=employee1,%s' % OU_PEOPLE, {
  145. 'objectclass': 'top extensibleObject'.split(),
  146. 'uid': 'employee1'})))
  147. except ldap.LDAPError as e:
  148. log.fatal('Add employee1 failed: error ' + e.message['desc'])
  149. assert False
  150. log.info('Add linktype to manager1')
  151. topology.standalone.modify_s('uid=manager1,%s' % OU_PEOPLE,
  152. [(ldap.MOD_ADD, LINKTYPE, 'uid=employee1,%s' % OU_PEOPLE)])
  153. log.info('Check managed attribute')
  154. check_attr_val(topology, 'uid=employee1,%s' % OU_PEOPLE, MANAGEDTYPE, 'uid=manager1,%s' % OU_PEOPLE)
  155. log.info('PASSED')
  156. def test_48294_run_0(topology):
  157. """
  158. Rename employee1 to employee2 and adjust the value of directReport by replace
  159. """
  160. _header(topology, 'Case 0 - Rename employee1 and adjust the link type value by replace')
  161. log.info('Rename employee1 to employee2')
  162. _modrdn_entry(topology, entry_dn='uid=employee1,%s' % OU_PEOPLE, new_rdn='uid=employee2')
  163. log.info('Modify the value of directReport to uid=employee2')
  164. try:
  165. topology.standalone.modify_s('uid=manager1,%s' % OU_PEOPLE,
  166. [(ldap.MOD_REPLACE, LINKTYPE, 'uid=employee2,%s' % OU_PEOPLE)])
  167. except ldap.LDAPError as e:
  168. log.fatal('Failed to replace uid=employee1 with employee2: ' + e.message['desc'])
  169. assert False
  170. log.info('Check managed attribute')
  171. check_attr_val(topology, 'uid=employee2,%s' % OU_PEOPLE, MANAGEDTYPE, 'uid=manager1,%s' % OU_PEOPLE)
  172. log.info('PASSED')
  173. def test_48294_run_1(topology):
  174. """
  175. Rename employee2 to employee3 and adjust the value of directReport by delete and add
  176. """
  177. _header(topology, 'Case 1 - Rename employee2 and adjust the link type value by delete and add')
  178. log.info('Rename employee2 to employee3')
  179. _modrdn_entry(topology, entry_dn='uid=employee2,%s' % OU_PEOPLE, new_rdn='uid=employee3')
  180. log.info('Modify the value of directReport to uid=employee3')
  181. try:
  182. topology.standalone.modify_s('uid=manager1,%s' % OU_PEOPLE,
  183. [(ldap.MOD_DELETE, LINKTYPE, 'uid=employee2,%s' % OU_PEOPLE)])
  184. except ldap.LDAPError as e:
  185. log.fatal('Failed to delete employee2: ' + e.message['desc'])
  186. assert False
  187. try:
  188. topology.standalone.modify_s('uid=manager1,%s' % OU_PEOPLE,
  189. [(ldap.MOD_ADD, LINKTYPE, 'uid=employee3,%s' % OU_PEOPLE)])
  190. except ldap.LDAPError as e:
  191. log.fatal('Failed to add employee3: ' + e.message['desc'])
  192. assert False
  193. log.info('Check managed attribute')
  194. check_attr_val(topology, 'uid=employee3,%s' % OU_PEOPLE, MANAGEDTYPE, 'uid=manager1,%s' % OU_PEOPLE)
  195. log.info('PASSED')
  196. def test_48294_run_2(topology):
  197. """
  198. Rename manager1 to manager2 and make sure the managed attribute value is updated
  199. """
  200. _header(topology, 'Case 2 - Rename manager1 to manager2 and make sure the managed attribute value is updated')
  201. log.info('Rename manager1 to manager2')
  202. _modrdn_entry(topology, entry_dn='uid=manager1,%s' % OU_PEOPLE, new_rdn='uid=manager2')
  203. log.info('Check managed attribute')
  204. check_attr_val(topology, 'uid=employee3,%s' % OU_PEOPLE, MANAGEDTYPE, 'uid=manager2,%s' % OU_PEOPLE)
  205. log.info('PASSED')
  206. if __name__ == '__main__':
  207. # Run isolated
  208. # -s for DEBUG mode
  209. CURRENT_FILE = os.path.realpath(__file__)
  210. pytest.main("-s %s" % CURRENT_FILE)