wait_for_async_feature_test.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. # --- BEGIN COPYRIGHT BLOCK ---
  2. # Copyright (C) 2016 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. from lib389 import DirSrv, Entry, tools, tasks
  16. from lib389.tools import DirSrvTools
  17. from lib389._constants import *
  18. from lib389.properties import *
  19. from lib389.tasks import *
  20. from lib389.utils import *
  21. from collections import Counter
  22. from lib389.topologies import topology_m2
  23. logging.getLogger(__name__).setLevel(logging.DEBUG)
  24. log = logging.getLogger(__name__)
  25. installation1_prefix = None
  26. WAITFOR_ASYNC_ATTR = "nsDS5ReplicaWaitForAsyncResults"
  27. @pytest.fixture(params=[(None, (4, 11)),
  28. ('2000', (0, 2)),
  29. ('0', (4, 11)),
  30. ('-5', (4, 11))])
  31. def waitfor_async_attr(topology_m2, request):
  32. """Sets attribute on all replicas"""
  33. attr_value = request.param[0]
  34. expected_result = request.param[1]
  35. # Run through all masters
  36. for num in range(1, 3):
  37. master = topology_m2.ms["master{}".format(num)]
  38. agmt = topology_m2.ms["master{}_agmts".format(num)].values()[0]
  39. try:
  40. if attr_value:
  41. log.info("Set %s: %s on %s" % (
  42. WAITFOR_ASYNC_ATTR, attr_value, master.serverid))
  43. mod = [(ldap.MOD_REPLACE, WAITFOR_ASYNC_ATTR, attr_value)]
  44. else:
  45. log.info("Delete %s from %s" % (
  46. WAITFOR_ASYNC_ATTR, master.serverid))
  47. mod = [(ldap.MOD_DELETE, WAITFOR_ASYNC_ATTR, None)]
  48. master.modify_s(agmt, mod)
  49. except ldap.LDAPError as e:
  50. log.error('Failed to set or delete %s attribute: (%s)' % (
  51. WAITFOR_ASYNC_ATTR, e.message['desc']))
  52. return (attr_value, expected_result)
  53. @pytest.fixture
  54. def entries(topology_m2, request):
  55. """Adds entries to the master1"""
  56. master1 = topology_m2.ms["master1"]
  57. TEST_OU = "test"
  58. test_dn = SUFFIX
  59. test_list = []
  60. log.info("Add 100 nested entries under replicated suffix on %s" % master1.serverid)
  61. for i in range(100):
  62. test_dn = 'ou=%s%s,%s' % (TEST_OU, i, test_dn)
  63. test_list.insert(0, test_dn)
  64. try:
  65. master1.add_s(Entry((test_dn,
  66. {'objectclass': 'top',
  67. 'objectclass': 'organizationalUnit',
  68. 'ou': TEST_OU})))
  69. except ldap.LDAPError as e:
  70. log.error('Failed to add entry (%s): error (%s)' % (test_dn,
  71. e.message['desc']))
  72. assert False
  73. log.info("Delete created entries")
  74. for test_dn in test_list:
  75. try:
  76. master1.delete_s(test_dn)
  77. except ldap.LDAPError as e:
  78. log.error('Failed to delete entry (%s): error (%s)' % (test_dn,
  79. e.message['desc']))
  80. assert False
  81. def fin():
  82. log.info("Clear the errors log in the end of the test case")
  83. with open(master1.errlog, 'w') as errlog:
  84. errlog.writelines("")
  85. request.addfinalizer(fin)
  86. def test_not_int_value(topology_m2):
  87. """Tests not integer value"""
  88. master1 = topology_m2.ms["master1"]
  89. agmt = topology_m2.ms["master1_agmts"]["m1_m2"]
  90. log.info("Try to set %s: wv1" % WAITFOR_ASYNC_ATTR)
  91. try:
  92. mod = [(ldap.MOD_REPLACE, WAITFOR_ASYNC_ATTR, "wv1")]
  93. master1.modify_s(agmt, mod)
  94. except ldap.LDAPError as e:
  95. assert e.message['desc'] == 'Invalid syntax'
  96. def test_multi_value(topology_m2):
  97. """Tests multi value"""
  98. master1 = topology_m2.ms["master1"]
  99. agmt = topology_m2.ms["master1_agmts"]["m1_m2"]
  100. log.info("agmt: %s" % agmt)
  101. log.info("Try to set %s: 100 and 101 in the same time (multi value test)" % (
  102. WAITFOR_ASYNC_ATTR))
  103. try:
  104. mod = [(ldap.MOD_ADD, WAITFOR_ASYNC_ATTR, "100")]
  105. master1.modify_s(agmt, mod)
  106. mod = [(ldap.MOD_ADD, WAITFOR_ASYNC_ATTR, "101")]
  107. master1.modify_s(agmt, mod)
  108. except ldap.LDAPError as e:
  109. assert e.message['desc'] == 'Object class violation'
  110. def test_value_check(topology_m2, waitfor_async_attr):
  111. """Checks that value has been set correctly"""
  112. attr_value = waitfor_async_attr[0]
  113. for num in range(1, 3):
  114. master = topology_m2.ms["master{}".format(num)]
  115. agmt = topology_m2.ms["master{}_agmts".format(num)].values()[0]
  116. log.info("Check attr %s on %s" % (WAITFOR_ASYNC_ATTR, master.serverid))
  117. try:
  118. if attr_value:
  119. entry = master.search_s(agmt, ldap.SCOPE_BASE, "%s=%s" % (
  120. WAITFOR_ASYNC_ATTR, attr_value))
  121. assert entry
  122. else:
  123. entry = master.search_s(agmt, ldap.SCOPE_BASE, "%s=*" % WAITFOR_ASYNC_ATTR)
  124. assert not entry
  125. except ldap.LDAPError as e:
  126. log.fatal('Search failed, error: ' + e.message['desc'])
  127. assert False
  128. def test_behavior_with_value(topology_m2, waitfor_async_attr, entries):
  129. """Tests replication behavior with valid
  130. nsDS5ReplicaWaitForAsyncResults attribute values
  131. """
  132. master1 = topology_m2.ms["master1"]
  133. master2 = topology_m2.ms["master2"]
  134. log.info("Set Replication Debugging loglevel for the errorlog")
  135. master1.setLogLevel(LOG_REPLICA)
  136. master2.setLogLevel(LOG_REPLICA)
  137. master1.modify_s("cn=config", [(ldap.MOD_REPLACE,
  138. 'nsslapd-logging-hr-timestamps-enabled', "off")])
  139. master2.modify_s("cn=config", [(ldap.MOD_REPLACE,
  140. 'nsslapd-logging-hr-timestamps-enabled', "off")])
  141. sync_dict = Counter()
  142. min_ap = waitfor_async_attr[1][0]
  143. max_ap = waitfor_async_attr[1][1]
  144. time.sleep(20)
  145. log.info("Gather all sync attempts within Counter dict, group by timestamp")
  146. with open(master1.errlog, 'r') as errlog:
  147. errlog_filtered = filter(lambda x: "waitfor_async_results" in x, errlog)
  148. # Watch only over unsuccessful sync attempts
  149. for line in errlog_filtered:
  150. if line.split()[3] != line.split()[4]:
  151. timestamp = line.split(']')[0]
  152. sync_dict[timestamp] += 1
  153. log.info("Take the most common timestamp and assert it has appeared " \
  154. "in the range from %s to %s times" % (min_ap, max_ap))
  155. most_common_val = sync_dict.most_common(1)[0][1]
  156. assert min_ap <= most_common_val <= max_ap
  157. if __name__ == '__main__':
  158. # Run isolated
  159. # -s for DEBUG mode
  160. CURRENT_FILE = os.path.realpath(__file__)
  161. pytest.main("-s %s" % CURRENT_FILE)