# --- BEGIN COPYRIGHT BLOCK --- # Copyright (C) 2015 Red Hat, Inc. # All rights reserved. # # License: GPL (version 3 or any later version). # See LICENSE for details. # --- END COPYRIGHT BLOCK --- # import os import sys import time import ldap import logging import pytest from lib389 import DirSrv, Entry, tools, tasks from lib389.tools import DirSrvTools from lib389._constants import * from lib389.properties import * from lib389.tasks import * from lib389.utils import * logging.getLogger(__name__).setLevel(logging.DEBUG) log = logging.getLogger(__name__) installation1_prefix = None class TopologyReplication(object): def __init__(self, master1, master2): master1.open() self.master1 = master1 master2.open() self.master2 = master2 @pytest.fixture(scope="module") def topology(request): global installation1_prefix os.environ['USE_VALGRIND'] = '1' if installation1_prefix: args_instance[SER_DEPLOYED_DIR] = installation1_prefix # Creating master 1... master1 = DirSrv(verbose=False) if installation1_prefix: args_instance[SER_DEPLOYED_DIR] = installation1_prefix args_instance[SER_HOST] = HOST_MASTER_1 args_instance[SER_PORT] = PORT_MASTER_1 args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_1 args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX args_master = args_instance.copy() master1.allocate(args_master) instance_master1 = master1.exists() if instance_master1: master1.delete() master1.create() master1.open() master1.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_1) # Creating master 2... master2 = DirSrv(verbose=False) if installation1_prefix: args_instance[SER_DEPLOYED_DIR] = installation1_prefix args_instance[SER_HOST] = HOST_MASTER_2 args_instance[SER_PORT] = PORT_MASTER_2 args_instance[SER_SERVERID_PROP] = SERVERID_MASTER_2 args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX args_master = args_instance.copy() master2.allocate(args_master) instance_master2 = master2.exists() if instance_master2: master2.delete() master2.create() master2.open() master2.replica.enableReplication(suffix=SUFFIX, role=REPLICAROLE_MASTER, replicaId=REPLICAID_MASTER_2) # # Create all the agreements # # Creating agreement from master 1 to master 2 properties = {RA_NAME: r'meTo_$host:$port', RA_BINDDN: defaultProperties[REPLICATION_BIND_DN], RA_BINDPW: defaultProperties[REPLICATION_BIND_PW], RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD], RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]} m1_m2_agmt = master1.agreement.create(suffix=SUFFIX, host=master2.host, port=master2.port, properties=properties) if not m1_m2_agmt: log.fatal("Fail to create a master -> master replica agreement") sys.exit(1) log.debug("%s created" % m1_m2_agmt) # Creating agreement from master 2 to master 1 properties = {RA_NAME: r'meTo_$host:$port', RA_BINDDN: defaultProperties[REPLICATION_BIND_DN], RA_BINDPW: defaultProperties[REPLICATION_BIND_PW], RA_METHOD: defaultProperties[REPLICATION_BIND_METHOD], RA_TRANSPORT_PROT: defaultProperties[REPLICATION_TRANSPORT]} m2_m1_agmt = master2.agreement.create(suffix=SUFFIX, host=master1.host, port=master1.port, properties=properties) if not m2_m1_agmt: log.fatal("Fail to create a master -> master replica agreement") sys.exit(1) log.debug("%s created" % m2_m1_agmt) # Allow the replicas to get situated with the new agreements... time.sleep(5) # # Initialize all the agreements # master1.agreement.init(SUFFIX, HOST_MASTER_2, PORT_MASTER_2) master1.waitForReplInit(m1_m2_agmt) # Check replication is working... if master1.testReplication(DEFAULT_SUFFIX, master2): log.info('Replication is working.') else: log.fatal('Replication is not working.') assert False # Clear out the tmp dir master1.clearTmpDir(__file__) return TopologyReplication(master1, master2) def test_ticket11111_set_purgedelay(topology): args = {REPLICA_PURGE_DELAY: '5', REPLICA_PURGE_INTERVAL: '5'} try: topology.master1.replica.setProperties(DEFAULT_SUFFIX, None, None, args) except: log.fatal('Failed to configure replica') assert False try: topology.master2.replica.setProperties(DEFAULT_SUFFIX, None, None, args) except: log.fatal('Failed to configure replica') assert False topology.master1.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-auditlog-logging-enabled', 'on')]) topology.master2.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'nsslapd-auditlog-logging-enabled', 'on')]) topology.master1.restart(10) topology.master2.restart(10) def test_ticket11111_1(topology): name = 'test_entry' dn = "cn=%s,%s" % (name, SUFFIX) topology.master1.add_s(Entry((dn , { 'objectclass': "top person".split(), 'sn': name, 'cn': name}))) # First do an update that is replicated mods = [(ldap.MOD_ADD, 'description', '5')] topology.master1.modify_s(dn, mods) nbtry = 0 while (nbtry <= 10): try: ent = topology.master2.getEntry(dn, ldap.SCOPE_BASE, "(objectclass=*)", ['description']) if ent.hasAttr('description') and ent.getValue('description') == '5': break except ldap.NO_SUCH_OBJECT: pass nbtry = nbtry + 1 time.sleep(1) assert nbtry <= 10 # Stop M2 so that it will not receive the next update topology.master2.stop(10) # ADD a new value that is not replicated mods = [(ldap.MOD_DELETE, 'description', '5')] topology.master1.modify_s(dn, mods) # Stop M1 so that it will keep del '5' that is unknown from master2 topology.master1.stop(10) # Get the sbin directory so we know where to replace 'ns-slapd' sbin_dir = get_sbin_dir(prefix=topology.master2.prefix) # Enable valgrind valgrind_enable(sbin_dir) # start M2 to do the next updates topology.master2.start(10) # ADD 'description' by '5' mods = [(ldap.MOD_DELETE, 'description', '5')] topology.master2.modify_s(dn, mods) # DEL 'description' by '5' mods = [(ldap.MOD_ADD, 'description', '5')] topology.master2.modify_s(dn, mods) # sleep of purgedelay so that the next update will purge the CSN_7 time.sleep(6) # ADD 'description' by '8' that purge the state info mods = [(ldap.MOD_ADD, 'description', '6')] topology.master2.modify_s(dn, mods) if valgrind_check_leak(topology.master2, 'csnset_dup'): log.error('test_csnset_dup: Memory leak is present!') else: log.info('test_csnset_dup: No leak is present!') if valgrind_check_leak(topology.master2, 'Invalid'): log.info('Valgrind reported invalid!') else: log.info('Valgrind is happy!') #log.info("You can attach yourself") #time.sleep(60) # Enable valgrind valgrind_disable(sbin_dir) topology.master1.start(10) def test_ticket11111_final(topology): topology.master1.delete() topology.master2.delete() log.info('Testcase PASSED') def run_isolated(): global installation1_prefix installation1_prefix = None topo = topology(True) test_ticket11111_set_purgedelay(topo) test_ticket11111_1(topo) if __name__ == '__main__': run_isolated()