ticket48944_test.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2017 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 pytest
  10. from lib389.tasks import *
  11. from lib389.utils import *
  12. from lib389.topologies import topology_m2c2 as topo
  13. from lib389._constants import (PLUGIN_ACCT_POLICY, DN_PLUGIN, DN_CONFIG, DN_DM, PASSWORD,
  14. DEFAULT_SUFFIX, SUFFIX)
  15. pytestmark = pytest.mark.tier2
  16. DEBUGGING = os.getenv("DEBUGGING", default=False)
  17. if DEBUGGING:
  18. logging.getLogger(__name__).setLevel(logging.DEBUG)
  19. else:
  20. logging.getLogger(__name__).setLevel(logging.INFO)
  21. log = logging.getLogger(__name__)
  22. ACCPOL_DN = "cn={},{}".format(PLUGIN_ACCT_POLICY, DN_PLUGIN)
  23. ACCP_CONF = "{},{}".format(DN_CONFIG, ACCPOL_DN)
  24. USER_PW = 'Secret123'
  25. def _last_login_time(topo, userdn, inst_name, last_login):
  26. """Find lastLoginTime attribute value for a given master/consumer"""
  27. if 'master' in inst_name:
  28. if (last_login == 'bind_n_check'):
  29. topo.ms[inst_name].simple_bind_s(userdn, USER_PW)
  30. topo.ms[inst_name].simple_bind_s(DN_DM, PASSWORD)
  31. entry = topo.ms[inst_name].search_s(userdn, ldap.SCOPE_BASE, 'objectClass=*', ['lastLoginTime'])
  32. else:
  33. if (last_login == 'bind_n_check'):
  34. topo.cs[inst_name].simple_bind_s(userdn, USER_PW)
  35. topo.cs[inst_name].simple_bind_s(DN_DM, PASSWORD)
  36. entry = topo.cs[inst_name].search_s(userdn, ldap.SCOPE_BASE, 'objectClass=*', ['lastLoginTime'])
  37. lastLogin = entry[0].lastLoginTime
  38. time.sleep(1)
  39. return lastLogin
  40. def _enable_plugin(topo, inst_name):
  41. """Enable account policy plugin and configure required attributes"""
  42. log.info('Enable account policy plugin and configure required attributes')
  43. if 'master' in inst_name:
  44. log.info('Configure Account policy plugin on {}'.format(inst_name))
  45. topo.ms[inst_name].simple_bind_s(DN_DM, PASSWORD)
  46. try:
  47. topo.ms[inst_name].plugins.enable(name=PLUGIN_ACCT_POLICY)
  48. topo.ms[inst_name].modify_s(ACCPOL_DN, [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0', ensure_bytes(ACCP_CONF))])
  49. topo.ms[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'alwaysrecordlogin', b'yes')])
  50. topo.ms[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'stateattrname', b'lastLoginTime')])
  51. topo.ms[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'altstateattrname', b'createTimestamp')])
  52. topo.ms[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'specattrname', b'acctPolicySubentry')])
  53. topo.ms[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'limitattrname', b'accountInactivityLimit')])
  54. topo.ms[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'accountInactivityLimit', b'3600')])
  55. except ldap.LDAPError as e:
  56. log.error('Failed to configure {} plugin for inst-{} error: {}'.format(PLUGIN_ACCT_POLICY, inst_name, str(e)))
  57. topo.ms[inst_name].restart(timeout=10)
  58. else:
  59. log.info('Configure Account policy plugin on {}'.format(inst_name))
  60. topo.cs[inst_name].simple_bind_s(DN_DM, PASSWORD)
  61. try:
  62. topo.cs[inst_name].plugins.enable(name=PLUGIN_ACCT_POLICY)
  63. topo.cs[inst_name].modify_s(ACCPOL_DN, [(ldap.MOD_REPLACE, 'nsslapd-pluginarg0', ensure_bytes(ACCP_CONF))])
  64. topo.cs[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'alwaysrecordlogin', b'yes')])
  65. topo.cs[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'stateattrname', b'lastLoginTime')])
  66. topo.cs[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'altstateattrname', b'createTimestamp')])
  67. topo.cs[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'specattrname', b'acctPolicySubentry')])
  68. topo.cs[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'limitattrname', b'accountInactivityLimit')])
  69. topo.cs[inst_name].modify_s(ACCP_CONF, [(ldap.MOD_REPLACE, 'accountInactivityLimit', b'3600')])
  70. except ldap.LDAPError as e:
  71. log.error('Failed to configure {} plugin for inst-{} error {}'.format(PLUGIN_ACCT_POLICY, inst_name, str(e)))
  72. topo.cs[inst_name].restart(timeout=10)
  73. def test_ticket48944(topo):
  74. """On a read only replica invalid state info can accumulate
  75. :id: 833be131-f3bf-493e-97c6-3121438a07b1
  76. :feature: Account Policy Plugin
  77. :setup: Two master and two consumer setup
  78. :steps: 1. Configure Account policy plugin with alwaysrecordlogin set to yes
  79. 2. Check if entries are synced across masters and consumers
  80. 3. Stop all masters and consumers
  81. 4. Start master1 and bind as user1 to create lastLoginTime attribute
  82. 5. Start master2 and wait for the sync of lastLoginTime attribute
  83. 6. Stop master1 and bind as user1 from master2
  84. 7. Check if lastLoginTime attribute is updated and greater than master1
  85. 8. Stop master2, start consumer1, consumer2 and then master2
  86. 9. Check if lastLoginTime attribute is updated on both consumers
  87. 10. Bind as user1 to both consumers and check the value is updated
  88. 11. Check if lastLoginTime attribute is not updated from consumers
  89. 12. Start master1 and make sure the lastLoginTime attribute is not updated on consumers
  90. 13. Bind as user1 from master1 and check if all masters and consumers have the same value
  91. 14. Check error logs of consumers for "deletedattribute;deleted" message
  92. :expectedresults: No accumulation of replica invalid state info on consumers
  93. """
  94. log.info("Ticket 48944 - On a read only replica invalid state info can accumulate")
  95. user_name = 'newbzusr'
  96. tuserdn = 'uid={}1,ou=people,{}'.format(user_name, SUFFIX)
  97. inst_list = ['master1', 'master2', 'consumer1', 'consumer2']
  98. for inst_name in inst_list:
  99. _enable_plugin(topo, inst_name)
  100. log.info('Sleep for 10secs for the server to come up')
  101. time.sleep(10)
  102. log.info('Add few entries to server and check if entries are replicated')
  103. for nos in range(10):
  104. userdn = 'uid={}{},ou=people,{}'.format(user_name, nos, SUFFIX)
  105. try:
  106. topo.ms['master1'].add_s(Entry((userdn, {
  107. 'objectclass': 'top person'.split(),
  108. 'objectclass': 'inetorgperson',
  109. 'cn': user_name,
  110. 'sn': user_name,
  111. 'userpassword': USER_PW,
  112. 'mail': '{}@redhat.com'.format(user_name)})))
  113. except ldap.LDAPError as e:
  114. log.error('Failed to add {} user: error {}'.format(userdn, e.message['desc']))
  115. raise e
  116. log.info('Checking if entries are synced across masters and consumers')
  117. entries_m1 = topo.ms['master1'].search_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid={}*'.format(user_name), ['uid=*'])
  118. exp_entries = str(entries_m1).count('dn: uid={}*'.format(user_name))
  119. entries_m2 = topo.ms['master2'].search_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid={}*'.format(user_name), ['uid=*'])
  120. act_entries = str(entries_m2).count('dn: uid={}*'.format(user_name))
  121. assert act_entries == exp_entries
  122. inst_list = ['consumer1', 'consumer2']
  123. for inst in inst_list:
  124. entries_other = topo.cs[inst].search_s(SUFFIX, ldap.SCOPE_SUBTREE, 'uid={}*'.format(user_name), ['uid=*'])
  125. act_entries = str(entries_other).count('dn: uid={}*'.format(user_name))
  126. assert act_entries == exp_entries
  127. topo.ms['master2'].stop(timeout=10)
  128. topo.ms['master1'].stop(timeout=10)
  129. topo.cs['consumer1'].stop(timeout=10)
  130. topo.cs['consumer2'].stop(timeout=10)
  131. topo.ms['master1'].start(timeout=10)
  132. lastLogin_m1_1 = _last_login_time(topo, tuserdn, 'master1', 'bind_n_check')
  133. log.info('Start master2 to sync lastLoginTime attribute from master1')
  134. topo.ms['master2'].start(timeout=10)
  135. time.sleep(5)
  136. log.info('Stop master1')
  137. topo.ms['master1'].stop(timeout=10)
  138. log.info('Bind as user1 to master2 and check if lastLoginTime attribute is greater than master1')
  139. lastLogin_m2_1 = _last_login_time(topo, tuserdn, 'master2', 'bind_n_check')
  140. assert lastLogin_m2_1 > lastLogin_m1_1
  141. log.info('Start all servers except master1')
  142. topo.ms['master2'].stop(timeout=10)
  143. topo.cs['consumer1'].start(timeout=10)
  144. topo.cs['consumer2'].start(timeout=10)
  145. topo.ms['master2'].start(timeout=10)
  146. time.sleep(10)
  147. log.info('Check if consumers are updated with lastLoginTime attribute value from master2')
  148. lastLogin_c1_1 = _last_login_time(topo, tuserdn, 'consumer1', 'check')
  149. assert lastLogin_c1_1 == lastLogin_m2_1
  150. lastLogin_c2_1 = _last_login_time(topo, tuserdn, 'consumer2', 'check')
  151. assert lastLogin_c2_1 == lastLogin_m2_1
  152. log.info('Check if lastLoginTime update in consumers not synced to master2')
  153. lastLogin_c1_2 = _last_login_time(topo, tuserdn, 'consumer1', 'bind_n_check')
  154. assert lastLogin_c1_2 > lastLogin_m2_1
  155. lastLogin_c2_2 = _last_login_time(topo, tuserdn, 'consumer2', 'bind_n_check')
  156. assert lastLogin_c2_2 > lastLogin_m2_1
  157. time.sleep(10) # Allow replication to kick in
  158. lastLogin_m2_2 = _last_login_time(topo, tuserdn, 'master2', 'check')
  159. assert lastLogin_m2_2 == lastLogin_m2_1
  160. log.info('Start master1 and check if its updating its older lastLoginTime attribute to consumers')
  161. topo.ms['master1'].start(timeout=10)
  162. time.sleep(10)
  163. lastLogin_c1_3 = _last_login_time(topo, tuserdn, 'consumer1', 'check')
  164. assert lastLogin_c1_3 == lastLogin_c1_2
  165. lastLogin_c2_3 = _last_login_time(topo, tuserdn, 'consumer2', 'check')
  166. assert lastLogin_c2_3 == lastLogin_c2_2
  167. log.info('Check if lastLoginTime update from master2 is synced to all masters and consumers')
  168. lastLogin_m2_3 = _last_login_time(topo, tuserdn, 'master2', 'bind_n_check')
  169. time.sleep(10) # Allow replication to kick in
  170. lastLogin_m1_2 = _last_login_time(topo, tuserdn, 'master1', 'check')
  171. lastLogin_c1_4 = _last_login_time(topo, tuserdn, 'consumer1', 'check')
  172. lastLogin_c2_4 = _last_login_time(topo, tuserdn, 'consumer2', 'check')
  173. assert lastLogin_m2_3 == lastLogin_m1_2 == lastLogin_c2_4 == lastLogin_c1_4
  174. log.info('Checking consumer error logs for replica invalid state info')
  175. assert not topo.cs['consumer2'].ds_error_log.match('.*deletedattribute;deleted.*')
  176. assert not topo.cs['consumer1'].ds_error_log.match('.*deletedattribute;deleted.*')
  177. if __name__ == '__main__':
  178. # Run isolated
  179. # -s for DEBUG mode
  180. CURRENT_FILE = os.path.realpath(__file__)
  181. pytest.main("-s %s" % CURRENT_FILE)