ticket48294_test.py 9.3 KB

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