From a378d4e06e5004191954d515e5244718a2d6ce21 Mon Sep 17 00:00:00 2001 From: Sankar Ramalingam Date: Wed, 13 Sep 2017 00:03:56 +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 | 275 +++++++++++++++++++++ 1 file changed, 275 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..853fdaf --- /dev/null +++ b/dirsrvtests/tests/suites/replication/changelog_test.py @@ -0,0 +1,275 @@ +# --- 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, ldap, logging, pytest +from lib389.replica import Replicas +from lib389.properties import TASK_WAIT +from lib389.idm.user import UserAccounts +from lib389.topologies import topology_st as topo +from lib389._constants import DEFAULT_SUFFIX, PASSWORD, DN_MAPPING_TREE, RDN_REPLICA, DEFAULT_CHANGELOG_DB, ReplicaRole + +TEST_ENTRY_NAME = 'replusr' +NEW_RDN_NAME = 'cl5usr' +ATTRIBUTES = ( +'replgen', 'csn', 'nsuniqueid', 'dn', 'change', 'newrdn', 'parentuniqueid', 'deleteoldrdn', 'deleteoldrdn') +CHANGE_TYPES = ('add', 'modify', 'modrdn', 'delete') +DN_REPLICA = '{},cn="{}",{}'.format(RDN_REPLICA, DEFAULT_SUFFIX, DN_MAPPING_TREE) + +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__) + + +@pytest.fixture(scope='module') +def configure_replica_changelog(topo, request): + """Configure replica and changelog for standalone instance""" + + log.info('Configure replica for standalone instance') + replicas = Replicas(topo.standalone) + replica = replicas.enable(suffix=DEFAULT_SUFFIX, role=ReplicaRole.MASTER, replicaID=1) + + def fin(): + log.info('Unconfigure changelog and replica for standalone instance') + replicas.disable(DEFAULT_SUFFIX) + + request.addfinalizer(fin) + return replicas + + +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.standalone, 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.standalone.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') + changelog_dir = os.path.join(os.path.dirname(topo.standalone.dbdir), DEFAULT_CHANGELOG_DB) + 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 changelog ldif files present') + + log.info('Running nsds5task to dump changelog database to a file') + try: + topo.standalone.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""" + + log.info('Checking changelog ldif file for ldap operations') + change_type_flag = False + count = 0 + if not os.stat(changelog_ldif).st_size > 0: + log.fatal('Changelog file-{} has no contents'.format(changelog_ldif)) + assert False + with open(changelog_ldif, 'r') as fh: + for line in fh: + if not line.strip(): + continue + elif line.startswith('changetype'): + ldap_operation = line.split(':')[-1].strip() + if ldap_operation in CHANGE_TYPES: + log.info('Found expected ldap operation type-{}'.format(ldap_operation)) + change_type_flag = True + count += 1 + else: + log.error('Found unexpected ldap operations type-{}'.format(ldap_operation)) + assert False + elif change_type_flag: + attr = line.split(':')[0] + if attr in ATTRIBUTES: + log.info('Expected attribute present-{}'.format(attr)) + else: + log.fatal('Missing LDAP operations-{}'.format(CHANGE_TYPES)) + assert False + + if count >= 4: + log.info('Found all the required ldap operations'.format(CHANGE_TYPES)) + else: + log.fatal('Some of the ldap operations type is missing') + assert False + + +def test_verify_changelog(topo, configure_replica_changelog): + """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, configure_replica_changelog): + """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.standalone.get_bak_dir(), 'online_backup') + log.info('Run db2bak script to take database backup') + try: + topo.standalone.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/{}'.format(DEFAULT_CHANGELOG_DB)) + if os.path.exists(backup_checkdir): + log.info('Database backup is created successfully') + else: + log.error('test_changelog5: backup directory does not exist -{}'.format(backup_checkdir)) + assert False + + log.info('Run bak2db to restore directory server') + try: + topo.standalone.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, configure_replica_changelog): + """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.standalone.get_bak_dir(), 'offline_backup') + + topo.standalone.stop() + log.info('Run db2bak to take database backup') + try: + topo.standalone.db2bak(backup_dir) + except ValueError: + log.fatal('test_changelog5: Offline backup failed') + assert False + + log.info('Run bak2db to restore directory server') + try: + topo.standalone.bak2db(backup_dir) + except ValueError: + log.fatal('test_changelog5: Offline restore failed') + assert False + topo.standalone.start() + + backup_checkdir = os.path.join(backup_dir, '.repl_changelog_backup/{}'.format(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.4