From b8a922ecaf15fa394296f73e94f612554c109f5f Mon Sep 17 00:00:00 2001 From: Barbora Smejkalova Date: Jan 13 2020 12:23:09 +0000 Subject: Issue 49761 - Fix CI test suite issues Description: Fixing failing ticket48755_test.py, so it would pass nightly tests. Also moved the test from tickets to suites/replication/regressions_test.py This code is NOT IN MERGEABLE state. The test passes on Fedora, RHEL7 and RHEL8 but I could use an advice with how to replace "search_s" so the test wouldn't use deprecated features, please. Relates: https://pagure.io/389-ds-base/issue/48755 Relates: https://pagure.io/389-ds-base/issue/49761 Reviewed by: vashirov (Thanks!) --- diff --git a/dirsrvtests/tests/suites/replication/regression_test.py b/dirsrvtests/tests/suites/replication/regression_test.py index 62c4c34..a948b53 100644 --- a/dirsrvtests/tests/suites/replication/regression_test.py +++ b/dirsrvtests/tests/suites/replication/regression_test.py @@ -10,6 +10,7 @@ import ldif import pytest import subprocess from lib389.idm.user import TEST_USER_PROPERTIES, UserAccounts +from lib389.pwpolicy import PwPolicyManager from lib389.utils import * from lib389.topologies import topology_m2 as topo_m2, TopologyMain, topology_m3 as topo_m3, create_topology, _remove_ssca_db from lib389._constants import * @@ -132,6 +133,54 @@ def create_entry(topo_m2, request): return tuser +def add_ou_entry(server, idx, parent): + ous = OrganizationalUnits(server, parent) + name = 'OU%d' % idx + ous.create(properties={'ou': '%s' % name}) + + +def add_user_entry(server, idx, parent): + users = UserAccounts(server, DEFAULT_SUFFIX, rdn=parent) + user_properties = { + 'uid': 'tuser%d' % idx, + 'givenname': 'test', + 'cn': 'Test User%d' % idx, + 'sn': 'user%d' % idx, + 'userpassword': PW_DM, + 'uidNumber' : '1000%d' % idx, + 'gidNumber': '2000%d' % idx, + 'homeDirectory': '/home/{}'.format('tuser%d' % idx) + } + users.create(properties=user_properties) + + +def del_user_entry(server, idx, parent): + users = UserAccounts(server, DEFAULT_SUFFIX, rdn=parent) + test_user = users.get('tuser%d' % idx) + test_user.delete() + + +def rename_entry(server, idx, ou_name, new_parent): + users = UserAccounts(server, DEFAULT_SUFFIX, rdn=ou_name) + name = 'tuser%d' % idx + rdn = 'uid=%s' % name + test_user = users.get(name) + test_user.rename(new_rdn=rdn, newsuperior=new_parent) + + +def add_ldapsubentry(server, parent): + pwp = PwPolicyManager(server) + policy_props = {'passwordStorageScheme': 'ssha', + 'passwordCheckSyntax': 'on', + 'passwordInHistory': '6', + 'passwordChange': 'on', + 'passwordMinAge': '0', + 'passwordExp': 'off', + 'passwordMustChange': 'off',} + log.info('Create password policy for subtree {}'.format(parent)) + pwp.create_subtree_policy(parent, policy_props) + + def test_double_delete(topo_m2, create_entry): """Check that double delete of the entry doesn't crash server @@ -696,6 +745,107 @@ def test_online_reinit_may_hang(topo_with_sigkill): pass +@pytest.mark.bz1314956 +@pytest.mark.ds48755 +def test_moving_entry_make_online_init_fail(topology_m2): + """ + Moving an entry could make the online init fail + + :id: e3895be7-884a-4e9f-80e3-24e9a5167c9e + :setup: Two masters replication setup + :steps: + 1. Generate DIT_0 + 2. Generate password policy for DIT_0 + 3. Create users for DIT_0 + 4. Turn idx % 2 == 0 users into tombstones + 5. Generate DIT_1 + 6. Move 'ou=OU0,ou=OU0,dc=example,dc=com' to DIT_1 + 7. Move 'ou=OU0,dc=example,dc=com' to DIT_1 + 8. Move idx % 2 == 1 users to 'ou=OU0,ou=OU0,ou=OU1,dc=example,dc=com' + 9. Init replicas + 10. Number of entries should match on both masters + + :expectedresults: + 1. Success + 2. Success + 3. Success + 4. Success + 5. Success + 6. Success + 7. Success + 8. Success + 9. Success + 10. Success + """ + + M1 = topology_m2.ms["master1"] + M2 = topology_m2.ms["master2"] + + log.info("Generating DIT_0") + idx = 0 + add_ou_entry(M1, idx, DEFAULT_SUFFIX) + log.info("Created entry: ou=OU0, dc=example, dc=com") + + ou0 = 'ou=OU%d' % idx + first_parent = '%s,%s' % (ou0, DEFAULT_SUFFIX) + add_ou_entry(M1, idx, first_parent) + log.info("Created entry: ou=OU0, ou=OU0, dc=example, dc=com") + + add_ldapsubentry(M1, first_parent) + + ou_name = 'ou=OU%d,ou=OU%d' % (idx, idx) + second_parent = 'ou=OU%d,%s' % (idx, first_parent) + for idx in range(0, 9): + add_user_entry(M1, idx, ou_name) + if idx % 2 == 0: + log.info("Turning tuser%d into a tombstone entry" % idx) + del_user_entry(M1, idx, ou_name) + + log.info('%s => %s => %s => 10 USERS' % (DEFAULT_SUFFIX, first_parent, second_parent)) + + log.info("Generating DIT_1") + idx = 1 + add_ou_entry(M1, idx, DEFAULT_SUFFIX) + log.info("Created entry: ou=OU1,dc=example,dc=com") + + third_parent = 'ou=OU%d,%s' % (idx, DEFAULT_SUFFIX) + add_ou_entry(M1, idx, third_parent) + log.info("Created entry: ou=OU1, ou=OU1, dc=example, dc=com") + + add_ldapsubentry(M1, third_parent) + + log.info("Moving %s to DIT_1" % second_parent) + OrganizationalUnits(M1, second_parent).get('OU0').rename(ou0, newsuperior=third_parent) + + log.info("Moving %s to DIT_1" % first_parent) + fourth_parent = '%s,%s' % (ou0, third_parent) + OrganizationalUnits(M1, first_parent).get('OU0').rename(ou0, newsuperior=fourth_parent) + + fifth_parent = '%s,%s' % (ou0, fourth_parent) + + ou_name = 'ou=OU0,ou=OU1' + log.info("Moving USERS to %s" % fifth_parent) + for idx in range(0, 9): + if idx % 2 == 1: + rename_entry(M1, idx, ou_name, fifth_parent) + + log.info('%s => %s => %s => %s => 10 USERS' % (DEFAULT_SUFFIX, third_parent, fourth_parent, fifth_parent)) + + log.info("Run Initialization.") + repl = ReplicationManager(DEFAULT_SUFFIX) + repl.wait_for_replication(M1, M2, timeout=5) + + m1entries = M1.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, + '(|(objectclass=ldapsubentry)(objectclass=nstombstone)(nsuniqueid=*))') + m2entries = M2.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, + '(|(objectclass=ldapsubentry)(objectclass=nstombstone)(nsuniqueid=*))') + + log.info("m1entry count - %d", len(m1entries)) + log.info("m2entry count - %d", len(m2entries)) + + assert len(m1entries) == len(m2entries) + + if __name__ == '__main__': # Run isolated # -s for DEBUG mode diff --git a/dirsrvtests/tests/tickets/ticket48755_test.py b/dirsrvtests/tests/tickets/ticket48755_test.py deleted file mode 100644 index 6b83f50..0000000 --- a/dirsrvtests/tests/tickets/ticket48755_test.py +++ /dev/null @@ -1,160 +0,0 @@ -# --- BEGIN COPYRIGHT BLOCK --- -# Copyright (C) 2016 Red Hat, Inc. -# All rights reserved. -# -# License: GPL (version 3 or any later version). -# See LICENSE for details. -# --- END COPYRIGHT BLOCK --- -# -import time -import pytest -from lib389.tasks import * -from lib389.utils import * -from lib389.topologies import topology_m2 - -pytestmark = pytest.mark.tier2 - -logging.getLogger(__name__).setLevel(logging.DEBUG) -log = logging.getLogger(__name__) - - -@pytest.fixture(scope="module") -def add_ou_entry(server, idx, myparent): - name = 'OU%d' % idx - dn = 'ou=%s,%s' % (name, myparent) - server.add_s(Entry((dn, {'objectclass': ['top', 'organizationalunit'], - 'ou': name}))) - time.sleep(1) - - -def add_user_entry(server, idx, myparent): - name = 'tuser%d' % idx - dn = 'uid=%s,%s' % (name, myparent) - server.add_s(Entry((dn, {'objectclass': ['top', 'person', 'organizationalPerson', 'inetorgperson'], - 'givenname': 'test', - 'sn': 'user%d' % idx, - 'cn': 'Test User%d' % idx, - 'userpassword': 'password'}))) - time.sleep(1) - - -def del_user_entry(server, idx, myparent): - name = 'tuser%d' % idx - dn = 'uid=%s,%s' % (name, myparent) - server.delete_s(dn) - time.sleep(1) - - -def add_ldapsubentry(server, myparent): - name = 'nsPwPolicyContainer' - container = 'cn=%s,%s' % (name, myparent) - server.add_s(Entry((container, {'objectclass': ['top', 'nsContainer'], - 'cn': '%s' % name}))) - - name = 'nsPwPolicyEntry' - pwpentry = 'cn=%s,%s' % (name, myparent) - pwpdn = 'cn="%s",%s' % (pwpentry, container) - server.add_s(Entry((pwpdn, {'objectclass': ['top', 'ldapsubentry', 'passwordpolicy'], - 'passwordStorageScheme': 'ssha', - 'passwordCheckSyntax': 'on', - 'passwordInHistory': '6', - 'passwordChange': 'on', - 'passwordMinAge': '0', - 'passwordExp': 'off', - 'passwordMustChange': 'off', - 'cn': '%s' % pwpentry}))) - - name = 'nsPwTemplateEntry' - tmplentry = 'cn=%s,%s' % (name, myparent) - tmpldn = 'cn="%s",%s' % (tmplentry, container) - server.add_s(Entry((tmpldn, {'objectclass': ['top', 'ldapsubentry', 'costemplate', 'extensibleObject'], - 'cosPriority': '1', - 'cn': '%s' % tmplentry}))) - - name = 'nsPwPolicy_CoS' - cos = 'cn=%s,%s' % (name, myparent) - server.add_s(Entry((cos, {'objectclass': ['top', 'ldapsubentry', 'cosPointerDefinition', 'cosSuperDefinition'], - 'costemplatedn': '%s' % tmpldn, - 'cosAttribute': 'pwdpolicysubentry default operational-default', - 'cn': '%s' % name}))) - time.sleep(1) - - -def test_ticket48755(topology_m2): - log.info("Ticket 48755 - moving an entry could make the online init fail") - - M1 = topology_m2.ms["master1"] - M2 = topology_m2.ms["master2"] - - log.info("Generating DIT_0") - idx = 0 - add_ou_entry(M1, idx, DEFAULT_SUFFIX) - - ou0 = 'ou=OU%d' % idx - parent0 = '%s,%s' % (ou0, DEFAULT_SUFFIX) - add_ou_entry(M1, idx, parent0) - - add_ldapsubentry(M1, parent0) - - parent00 = 'ou=OU%d,%s' % (idx, parent0) - for idx in range(0, 9): - add_user_entry(M1, idx, parent00) - if idx % 2 == 0: - log.info("Turning tuser%d into a tombstone entry" % idx) - del_user_entry(M1, idx, parent00) - - log.info('%s => %s => %s => 10 USERS' % (DEFAULT_SUFFIX, parent0, parent00)) - - log.info("Generating DIT_1") - idx = 1 - add_ou_entry(M1, idx, DEFAULT_SUFFIX) - - parent1 = 'ou=OU%d,%s' % (idx, DEFAULT_SUFFIX) - add_ou_entry(M1, idx, parent1) - - add_ldapsubentry(M1, parent1) - - log.info("Moving %s to DIT_1" % parent00) - M1.rename_s(parent00, ou0, newsuperior=parent1, delold=1) - time.sleep(1) - - log.info("Moving %s to DIT_1" % parent0) - parent01 = '%s,%s' % (ou0, parent1) - M1.rename_s(parent0, ou0, newsuperior=parent01, delold=1) - time.sleep(1) - - parent001 = '%s,%s' % (ou0, parent01) - log.info("Moving USERS to %s" % parent0) - for idx in range(0, 9): - if idx % 2 == 1: - name = 'tuser%d' % idx - rdn = 'uid=%s' % name - dn = 'uid=%s,%s' % (name, parent01) - M1.rename_s(dn, rdn, newsuperior=parent001, delold=1) - time.sleep(1) - - log.info('%s => %s => %s => %s => 10 USERS' % (DEFAULT_SUFFIX, parent1, parent01, parent001)) - - log.info("Run Consumer Initialization.") - m1_m2_agmt = M1.agreement.list(suffix=DEFAULT_SUFFIX)[0].dn - M1.startReplication_async(m1_m2_agmt) - M1.waitForReplInit(m1_m2_agmt) - time.sleep(2) - - m1entries = M1.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, - '(|(objectclass=ldapsubentry)(objectclass=nstombstone)(nsuniqueid=*))') - m2entries = M2.search_s(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, - '(|(objectclass=ldapsubentry)(objectclass=nstombstone)(nsuniqueid=*))') - - log.info("m1entry count - %d", len(m1entries)) - log.info("m2entry count - %d", len(m2entries)) - - assert len(m1entries) == len(m2entries) - log.info('PASSED') - - -if __name__ == '__main__': - # Run isolated - # -s for DEBUG mode - CURRENT_FILE = os.path.realpath(__file__) - pytest.main("-s %s" % CURRENT_FILE)