From 134555dadc85452b796e0c255c30d11eaa3cd571 Mon Sep 17 00:00:00 2001 From: Sankar Ramalingam Date: Fri, 15 Sep 2017 06:58:25 +0530 Subject: [PATCH] Ticket #48085 - CI tests - replication cl5 Description: Adding changelog5 tests for replication. Test cases will check if changelog dump contains all the required ldap operations and its attributes. https://pagure.io/389-ds-base/issue/48085 Reviewed by: ? --- .../tests/suites/replication/changelog_test.py | 254 +++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100755 dirsrvtests/tests/suites/replication/changelog_test.py diff --git a/dirsrvtests/tests/suites/replication/changelog_test.py b/dirsrvtests/tests/suites/replication/changelog_test.py new file mode 100755 index 0000000..26af12d --- /dev/null +++ b/dirsrvtests/tests/suites/replication/changelog_test.py @@ -0,0 +1,254 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# Copyright (C) 2017 Red Hat, Inc. +# All rights reserved. +# +# License: GPL (version 3 or any later version). +# See LICENSE for details. +# --- END COPYRIGHT BLOCK --- +# +import os, re +import ldap, logging, pytest +from lib389.properties import TASK_WAIT +from lib389.replica import Replicas +from lib389.idm.user import UserAccounts +from lib389.topologies import topology_m2 as topo +from lib389._constants import * + +TEST_ENTRY_NAME = 'replusr' +NEW_RDN_NAME = 'cl5usr' +ATTRIBUTES = ['replgen:', 'csn:', 'nsuniqueid:', 'dn:'] +CHANGETYPES = ['changetype: add', 'changetype: modify', 'changetype: modrdn', + 'changetype: delete'] + +DEBUGGING = os.getenv('DEBUGGING', default=False) +if DEBUGGING: + logging.getLogger(__name__).setLevel(logging.DEBUG) +else: + logging.getLogger(__name__).setLevel(logging.INFO) +log = logging.getLogger(__name__) + + +def _perform_ldap_operations(topo): + """Add a test user, modify description, modrdn user and delete it""" + + log.info('Adding user {}'.format(TEST_ENTRY_NAME)) + users = UserAccounts(topo.ms['master1'], DEFAULT_SUFFIX) + user_properties = { + 'uid': TEST_ENTRY_NAME, + 'cn': TEST_ENTRY_NAME, + 'sn': TEST_ENTRY_NAME, + 'uidNumber': '1001', + 'gidNumber': '2001', + 'userpassword': PASSWORD, + 'description': 'userdesc', + 'homeDirectory': '/home/{}'.format(TEST_ENTRY_NAME)} + tuser = users.create(properties=user_properties) + tuser.replace('description', 'newdesc') + log.info('Modify RDN of user {}'.format(tuser.dn)) + try: + topo.ms['master1'].modrdn_s(tuser.dn, 'uid={}'.format(NEW_RDN_NAME), 0) + except ldap.LDAPError as e: + log.fatal('Failed to modrdn entry {}'.format(tuser.dn)) + raise e + tuser = users.get(NEW_RDN_NAME) + log.info('Deleting user-{}'.format(tuser.dn)) + tuser.delete() + + +def _create_changelog_dump(topo): + """Dump changelog using nss5task and check if ldap operations are logged""" + + log.info('Dump changelog using nss5task and check if ldap operations are logged') + db_dir = os.path.dirname(topo.ms['master1'].dbdir) + changelog_dir = os.path.join(db_dir, DEFAULT_CHANGELOG_DB) + replicas = Replicas(topo.ms["master1"]) + dn_replica = replicas.get_dn(DEFAULT_SUFFIX) + log.info('Remove ldif files, if present in-{}'.format(changelog_dir)) + for files in os.listdir(changelog_dir): + if files.endswith('.ldif'): + changelog_file = os.path.join(changelog_dir, files) + try: + os.remove(changelog_file) + except OSError as e: + log.fatal('Failed to remove ldif file-{}'.format(changelog_file)) + raise e + log.info('Existing changelog ldif file-{} removed'.format(changelog_file)) + else: + log.info('No existing changelog ldif files present') + + log.info('Running nsds5task to dump changelog database to a file') + try: + topo.ms['master1'].modify_s(dn_replica, [(ldap.MOD_REPLACE, 'nsds5task', 'cl2ldif')]) + except ldap.LDAPError as e: + log.fatal('Failed to dump changelog to ldif file') + raise e + + log.info('Check if changelog ldif file exist in-{}'.format(changelog_dir)) + for files in os.listdir(changelog_dir): + if files.endswith('.ldif'): + changelog_ldif = os.path.join(changelog_dir, files) + log.info('Changelog ldif file exist-{}'.format(changelog_ldif)) + return changelog_ldif + else: + log.fatal('Changelog ldif file does not exist in-{}'.format(changelog_dir)) + assert False + + +def _check_changelog_ldif(topo, changelog_ldif): + """Check changelog ldif file for ldap operations and attributes""" + + log.info('Checking changelog ldif file for ldap operations') + with open(changelog_ldif, 'r') as fh: + contents = fh.read() + # Check if required changetype operations exist in changelog ldif file + log.info('Checking if all required changetype operations are present') + for changetype in CHANGETYPES: + if changetype in contents: + log.info('Found ldap operation-{}'.format(changetype)) + else: + log.fatal('Missing ldap operation-{}'.format(changetype)) + assert False + # Count the pattern match of each attribute in changelog ldif file + log.info('Checking changelog ldif file for all required attributes') + for attr in ATTRIBUTES: + if attr in contents: + count = len(re.findall(r'(^)' + attr, contents, re.MULTILINE)) + if count >= 4: + log.info('Count-{} found for attribute-{}'.format(count, attr)) + else: + log.fatal('Expected count >4, actual count-{} for attribute-{}'.format(count, attr)) + assert False + else: + log.fatal('Missing attribute-{}'.format(attr)) + assert False + + +def test_verify_changelog(topo): + """Check if changelog is logging ldap operations + + :id: 16347170-46cf-44f5-878e-16974ed3c394 + :feature: Changelog5 + :setup: Standalone instance with replica and changelog configured. + :steps: 1. Add user to server. + 2. Perform ldap modify, modrdn and delete operations. + 3. Dump the changelog to a file using nsds5task. + 4. Check if changelog is updated with ldap operations. + :expectedresults: + 1. Add user should PASS. + 2. Ldap operations should PASS. + 3. Changelog should be dumped successfully. + 4. Changelog dump file should contain ldap operations + """ + + log.info('LDAP operations add, modify, modrdn and delete') + _perform_ldap_operations(topo) + changelog_ldif = _create_changelog_dump(topo) + _check_changelog_ldif(topo, changelog_ldif) + + +def test_verify_changelog_online_backup(topo): + """Check if changelog is logging ldap operations + + :id: 196747c9-8a4b-4f76-a383-42e4310b0dbb + :feature: Changelog5 + :setup: Standalone instance with replica and changelog configured. + :steps: 1. Add user to server. + 2. Take online backup using db2bak task. + 3. Restore the database using bak2db task. + 4. Perform ldap modify, modrdn and delete operations. + 5. Dump the changelog to a file using nsds5task. + 6. Check if changelog is updated with ldap operations. + :expectedresults: + 1. Add user should PASS. + 2. Backup of database should PASS. + 3. Restore of database should PASS. + 4. Ldap operations should PASS. + 5. Changelog should be dumped successfully. + 6. Changelog dump file should contain ldap operations + """ + + backup_dir = os.path.join(topo.ms['master1'].get_bak_dir(), 'online_backup') + log.info('Run db2bak script to take database backup') + try: + topo.ms['master1'].tasks.db2bak(backup_dir=backup_dir, args={TASK_WAIT: True}) + except ValueError: + log.fatal('test_changelog5: Online backup failed') + assert False + + backup_checkdir = os.path.join(backup_dir, '.repl_changelog_backup', DEFAULT_CHANGELOG_DB) + if os.path.exists(backup_checkdir): + log.info('Database backup is created successfully') + else: + log.fatal('test_changelog5: backup directory does not exist -{}'.format(backup_checkdir)) + assert False + + log.info('Run bak2db to restore directory server') + try: + topo.ms['master1'].tasks.bak2db(backup_dir=backup_dir, args={TASK_WAIT: True}) + except ValueError: + log.fatal('test_changelog5: Online restore failed') + assert False + + log.info('LDAP operations add, modify, modrdn and delete') + _perform_ldap_operations(topo) + changelog_ldif = _create_changelog_dump(topo) + _check_changelog_ldif(topo, changelog_ldif) + + +def test_verify_changelog_offline_backup(topo): + """Check if changelog is logging ldap operations + + :id: cbf84dcc-2baa-4563-bb54-07645339faca + :feature: Changelog5 + :setup: Standalone instance with replica and changelog configured. + :steps: 1. Add user to server. + 2. Stop server and take offline backup using db2bak. + 3. Restore the database using bak2db. + 4. Perform ldap modify, modrdn and delete operations. + 5. Start the server and dump the changelog using nsds5task. + 6. Check if changelog is updated with ldap operations. + :expectedresults: + 1. Add user should PASS. + 2. Backup of database should PASS. + 3. Restore of database should PASS. + 4. Ldap operations should PASS. + 5. Changelog should be dumped successfully. + 6. Changelog dump file should contain ldap operations + """ + + backup_dir = os.path.join(topo.ms['master1'].get_bak_dir(), 'offline_backup') + + topo.ms['master1'].stop() + log.info('Run db2bak to take database backup') + try: + topo.ms['master1'].db2bak(backup_dir) + except ValueError: + log.fatal('test_changelog5: Offline backup failed') + assert False + + log.info('Run bak2db to restore directory server') + try: + topo.ms['master1'].bak2db(backup_dir) + except ValueError: + log.fatal('test_changelog5: Offline restore failed') + assert False + topo.ms['master1'].start() + + backup_checkdir = os.path.join(backup_dir, '.repl_changelog_backup', DEFAULT_CHANGELOG_DB) + if os.path.exists(backup_checkdir): + log.info('Database backup is created successfully') + else: + log.fatal('test_changelog5: backup directory does not exist -{}'.format(backup_checkdir)) + assert False + + log.info('LDAP operations add, modify, modrdn and delete') + _perform_ldap_operations(topo) + changelog_ldif = _create_changelog_dump(topo) + _check_changelog_ldif(topo, changelog_ldif) + + +if __name__ == '__main__': + # Run isolated + # -s for DEBUG mode + CURRENT_FILE = os.path.realpath(__file__) + pytest.main('-s {}'.format(CURRENT_FILE)) -- 2.7.5