Esempio n. 1
0
    def set_state(self, new_state):
        new_state = new_state.lower()
        suffix = self.get_attr_val_utf8('nsslapd-suffix')
        try:
            mt = self._mts.get(suffix)
        except ldap.NO_SUCH_OBJECT:
            raise ValueError(
                "Backend missing mapping tree entry, unable to set configuration"
            )

        if new_state not in [
                'backend', 'disabled', 'referral', 'referral on update'
        ]:
            raise ValueError(
                f"Invalid backend state {new_state}, value must be one of the following: 'backend', 'disabled',  'referral',  'referral on update'"
            )

        # Can not change state of replicated backend
        replicas = Replicas(self._instance)
        try:
            # Check if replication is enabled
            replicas.get(suffix)
            raise ValueError(
                "Can not change the backend state of a replicated suffix")
        except ldap.NO_SUCH_OBJECT:
            pass

        # Ok, change the state
        mt.replace('nsslapd-state', new_state)
Esempio n. 2
0
    def get_agmt_maxcsn(self):
        """Get the agreement maxcsn from the database RUV entry
        :returns: CSN string if found, otherwise None is returned
        """
        from lib389.replica import Replicas
        suffix = self.get_attr_val_utf8(REPL_ROOT)
        agmt_name = self.get_attr_val_utf8('cn')
        replicas = Replicas(self._instance)
        replica = replicas.get(suffix)
        maxcsns = replica.get_ruv_agmt_maxcsns()

        if maxcsns is None or len(maxcsns) == 0:
            self._log.debug(
                'get_agmt_maxcsn - Failed to get agmt maxcsn from RUV')
            return None

        for csn in maxcsns:
            comps = csn.split(';')
            if agmt_name == comps[1]:
                # same replica, get maxcsn
                if len(comps) < 6:
                    return None
                else:
                    return comps[5]

        self._log.debug(
            'get_agmt_maxcsn - did not find matching agmt maxcsn from RUV')
        return None
Esempio n. 3
0
def test_demote_fail(topo, new_suffixes, clean_up, role_from):
    """Check that replica demote method fails
    when demoted to wrong direction

    :feature: Replication
    :steps: 1. Enable replication on the instance
            2. Try to demote it to wrong role
               (for example, consumer-supplier, hub-supplier)
            3. Disable replication
    :expectedresults: Replica shouldn't be demoted
    """

    inst = topo.ins["standalone1"]

    log.info("Enable replication on instance with a role - {}".format(
        role_from.name))
    replicas = Replicas(inst)
    replica = replicas.enable(suffix=NEW_SUFFIX,
                              role=role_from,
                              replicaID=REPLICA_SUPPLIER_ID)

    for role_to in [x for x in range(1, 4) if x >= role_from.value]:
        role_to = ReplicaRole(role_to)
        log.info("Try to demote replica to {}".format(role_to.name))
        with pytest.raises(ValueError):
            replica.demote(newrole=role_to)
Esempio n. 4
0
def test_demote(topo, new_suffixes, clean_up, role_from, role_to):
    """Check that replica demote method works properly

    :feature: Replication
    :steps: 1. Enable replication on the instance
            2. Demote it to another role
               (check supplier-hub, supplier-consumer, hub-consumer)
            3. Check that role was successfully changed
            4. Disable replication
    :expectedresults: No errors happen, replica successfully demoted
    """

    inst = topo.ins["standalone1"]

    log.info("Enable replication on instance with a role - {}".format(
        role_from.name))
    replicas = Replicas(inst)
    replica = replicas.enable(suffix=NEW_SUFFIX,
                              role=role_from,
                              replicaID=REPLICA_SUPPLIER_ID)

    log.info("Promote replica to {}".format(role_to.name))
    replica.demote(newrole=role_to)

    log.info("Check that replica was successfully promoted")
    replica_role = replica.get_role()
    assert replica_role == role_to
Esempio n. 5
0
def test_replica_num_add(topo, attr, too_small, too_big, overflow, notnum, valid):
    """Test all the number values you can set for a replica config entry

    :id: a8b47d4a-a089-4d70-8070-e6181209bf92
    :parametrized: yes
    :setup: standalone instance
    :steps:
        1. Use a value that is too small
        2. Use a value that is too big
        3. Use a value that overflows the int
        4. Use a value with character value (not a number)
        5. Use a valid value
    :expectedresults:
        1. Add is rejected
        2. Add is rejected
        3. Add is rejected
        4. Add is rejected
        5. Add is allowed
    """
    replica_reset(topo)

    replicas = Replicas(topo.standalone)

    # Test too small
    perform_invalid_create(replicas, replica_dict, attr, too_small)
    # Test too big
    perform_invalid_create(replicas, replica_dict, attr, too_big)
    # Test overflow
    perform_invalid_create(replicas, replica_dict, attr, overflow)
    # test not a number
    perform_invalid_create(replicas, replica_dict, attr, notnum)
    # Test valid value
    my_replica = copy.deepcopy(replica_dict)
    my_replica[attr] = valid
    replicas.create(properties=my_replica)
Esempio n. 6
0
def replica_setup(topo):
    """Add a valid replica config entry to modify
    """
    replicas = Replicas(topo.standalone)
    for r in replicas.list():
        r.delete()
    return replicas.create(properties=replica_dict)
Esempio n. 7
0
def test_ticket50232_normal(topology_st):
    """
    The fix for ticket 50232


    The test sequence is:
    - create suffix
    - add suffix entry and some child entries
    - "normally" done after populating suffix: enable replication
    - get RUV and database generation
    - export -r
    - import
    - get RUV and database generation
    - assert database generation has not changed
    """

    log.info('Testing Ticket 50232 - export creates not imprtable ldif file, normal creation order')

    topology_st.standalone.backend.create(NORMAL_SUFFIX, {BACKEND_NAME: NORMAL_BACKEND_NAME})
    topology_st.standalone.mappingtree.create(NORMAL_SUFFIX, bename=NORMAL_BACKEND_NAME, parent=None)

    _populate_suffix(topology_st.standalone, NORMAL_BACKEND_NAME)

    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl._ensure_changelog(topology_st.standalone)
    replicas = Replicas(topology_st.standalone)
    replicas.create(properties={
        'cn': 'replica',
        'nsDS5ReplicaRoot': NORMAL_SUFFIX,
        'nsDS5ReplicaId': '1',
        'nsDS5Flags': '1',
        'nsDS5ReplicaType': '3'
        })

    _test_export_import(topology_st.standalone, NORMAL_SUFFIX, NORMAL_BACKEND_NAME)
Esempio n. 8
0
    def resume_all_replicas(self):
        """Resume all agreements in the class instance"""

        for inst in self.all_insts.values():
            replicas = Replicas(inst)
            replica = replicas.get(DEFAULT_SUFFIX)
            for agreement in replica.get_agreements().list():
                agreement.resume()
Esempio n. 9
0
 def fin():
     for num in range(1, 4):
         try:
             replicas = Replicas(topo.ins["standalone{}".format(num)])
             replicas.disable(NEW_SUFFIX)
             log.info("standalone{} is disabled now".format(num))
         except:
             pass
Esempio n. 10
0
def test_cl_encryption_setup_process(topo):
    """Take an already working replication deployment, and setup changelog
    encryption

    :id: 1a1b7d29-69f5-4f0e-91c4-e7f66140ff17
    :setup: Master Instance, Consumer Instance
    :steps:
        1. Enable TLS for the server
        2. Export changelog
        3. Enable changelog encryption
        4. Import changelog
        5. Verify replication is still working
    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
    """

    supplier = topo.ms['master1']
    consumer = topo.cs['consumer1']

    # Enable TLS
    log.info('Enable TLS ...')
    supplier.enable_tls()
    consumer.enable_tls()

    # Export changelog
    log.info('Export changelog ...')
    replicas = Replicas(supplier)
    replica = replicas.get(DEFAULT_SUFFIX)
    replica.begin_task_cl2ldif()
    replica.task_finished()

    # Enable changelog encryption
    log.info('Enable changelog encryption ...')
    dse_ldif = DSEldif(supplier)
    supplier.stop()
    if ds_supports_new_changelog():
        changelog = 'cn=changelog,{}'.format(DN_USERROOT_LDBM)
    else:
        changelog = DN_CHANGELOG
    dse_ldif.replace(changelog, 'nsslapd-encryptionalgorithm', 'AES')
    if dse_ldif.get(changelog, 'nsSymmetricKey'):
        dse_ldif.delete(changelog, 'nsSymmetricKey')
    supplier.start()

    # Import changelog
    log.info('Import changelog ...')
    replica.begin_task_ldif2cl()
    replica.task_finished()

    # Verify replication is still working
    log.info('Test replication is still working ...')
    assert replica.test_replication([consumer])
Esempio n. 11
0
def fractional_server_to_replica(server, replica):
    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl.ensure_agreement(server, replica)
    replica_server = Replicas(server).get(DEFAULT_SUFFIX)
    agmt_server = replica_server.get_agreements().list()[0]
    agmt_server.replace_many(
        ('nsDS5ReplicatedAttributeListTotal', '(objectclass=*) $ EXCLUDE telephoneNumber'),
        ('nsDS5ReplicatedAttributeList', '(objectclass=*) $ EXCLUDE telephoneNumber'),
        ('nsds5ReplicaStripAttrs', 'modifiersname modifytimestamp'),
    )
Esempio n. 12
0
def test_csnpurge_large_valueset(topo_m2):
    """Test csn generator test

    :id: 63e2bdb2-0a8f-4660-9465-7b80a9f72a74
    :setup: MMR with 2 masters
    :steps:
        1. Create a test_user
        2. add a large set of values (more than 10)
        3. delete all the values (more than 10)
        4. configure the replica to purge those values (purgedelay=5s)
        5. Waiting for 6 second
        6. do a series of update
    :expectedresults:
        1. Should succeeds
        2. Should succeeds
        3. Should succeeds
        4. Should succeeds
        5. Should succeeds
        6. Should not crash
    """
    m1 = topo_m2.ms["master2"]

    test_user = UserAccount(m1, TEST_ENTRY_DN)
    if test_user.exists():
        log.info('Deleting entry {}'.format(TEST_ENTRY_DN))
        test_user.delete()
    test_user.create(
        properties={
            'uid': TEST_ENTRY_NAME,
            'cn': TEST_ENTRY_NAME,
            'sn': TEST_ENTRY_NAME,
            'userPassword': TEST_ENTRY_NAME,
            'uidNumber': '1000',
            'gidNumber': '2000',
            'homeDirectory': '/home/mmrepl_test',
        })

    # create a large value set so that it is sorted
    for i in range(1, 20):
        test_user.add('description', 'value {}'.format(str(i)))

    # delete all values of the valueset
    for i in range(1, 20):
        test_user.remove('description', 'value {}'.format(str(i)))

    # set purging delay to 5 second and wait more that 5second
    replicas = Replicas(m1)
    replica = replicas.list()[0]
    log.info('nsds5ReplicaPurgeDelay to 5')
    replica.set('nsds5ReplicaPurgeDelay', '5')
    time.sleep(6)

    # add some new values to the valueset containing entries that should be purged
    for i in range(21, 25):
        test_user.add('description', 'value {}'.format(str(i)))
Esempio n. 13
0
def test_healthcheck_replication_replica_not_reachable(topology_m2):
    """Check if HealthCheck returns DSREPLLE0005 code

    :id: d452a564-7b82-4c1a-b331-a71abbd82a10
    :setup: Replicated topology
    :steps:
        1. Create a replicated topology
        2. On M1, set nsds5replicaport for the replication agreement to an unreachable port on the replica
        3. Use HealthCheck without --json option
        4. Use HealthCheck with --json option
        5. On M1, set nsds5replicaport for the replication agreement to a reachable port number
        6. Use HealthCheck without --json option
        7. Use HealthCheck with --json option
    :expectedresults:
        1. Success
        2. Success
        3. Healthcheck reports DSREPLLE0005 code and related details
        4. Healthcheck reports DSREPLLE0005 code and related details
        5. Success
        6. Healthcheck reports no issue found
        7. Healthcheck reports no issue found
    """

    RET_CODE = 'DSREPLLE0005'

    M1 = topology_m2.ms['supplier1']
    M2 = topology_m2.ms['supplier2']

    set_changelog_trimming(M1)

    log.info(
        'Set nsds5replicaport for the replication agreement to an unreachable port'
    )
    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl.wait_for_replication(M1, M2)

    replica_m1 = Replicas(M1).get(DEFAULT_SUFFIX)
    agmt_m1 = replica_m1.get_agreements().list()[0]
    agmt_m1.replace('nsds5replicaport', '4389')
    # Should generates updates here to insure that we starts a new replication session
    # and really try to connect to the consumer
    with suppress(Exception):
        repl.wait_for_replication(M1, M2, timeout=5)

    run_healthcheck_and_flush_log(topology_m2, M1, RET_CODE, json=False)
    run_healthcheck_and_flush_log(topology_m2, M1, RET_CODE, json=True)

    log.info(
        'Set nsds5replicaport for the replication agreement to a reachable port'
    )
    agmt_m1.replace('nsDS5ReplicaPort', '{}'.format(M2.port))
    repl.wait_for_replication(M1, M2)

    run_healthcheck_and_flush_log(topology_m2, M1, CMD_OUTPUT, json=False)
    run_healthcheck_and_flush_log(topology_m2, M1, JSON_OUTPUT, json=True)
Esempio n. 14
0
def test_lastupdate_attr_before_init(topo_nr):
    """Check that LastUpdate replica attributes show right values

    :id: bc8ce431-ff65-41f5-9331-605cbcaaa887
    :customerscenario: True
    :setup: Replication setup with supplier and consumer instances
            without initialization
    :steps:
        1. Check nsds5replicaLastUpdateStart value
        2. Check nsds5replicaLastUpdateEnd value
        3. Check nsds5replicaLastUpdateStatus value
        4. Check nsds5replicaLastUpdateStatusJSON is parsable
    :expectedresults:
        1. nsds5replicaLastUpdateStart should be equal to 0
        2. nsds5replicaLastUpdateEnd should be equal to 0
        3. nsds5replicaLastUpdateStatus should not be equal
           to "Replica acquired successfully: Incremental update started"
        4. Success
    """

    supplier = topo_nr.ins["standalone1"]
    consumer = topo_nr.ins["standalone2"]

    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl.create_first_supplier(supplier)

    # Manually create an un-synced consumer.

    consumer_replicas = Replicas(consumer)
    consumer_replicas.create(
        properties={
            'cn': 'replica',
            'nsDS5ReplicaRoot': DEFAULT_SUFFIX,
            'nsDS5ReplicaId': '65535',
            'nsDS5Flags': '0',
            'nsDS5ReplicaType': '2',
        })

    agmt = repl.ensure_agreement(supplier, consumer)
    with pytest.raises(Exception):
        repl.wait_for_replication(supplier, consumer, timeout=5)

    assert agmt.get_attr_val_utf8(
        'nsds5replicaLastUpdateStart') == "19700101000000Z"
    assert agmt.get_attr_val_utf8(
        "nsds5replicaLastUpdateEnd") == "19700101000000Z"
    assert "replica acquired successfully" not in agmt.get_attr_val_utf8_l(
        "nsds5replicaLastUpdateStatus")

    # make sure the JSON attribute is parsable
    json_status = agmt.get_attr_val_utf8("nsds5replicaLastUpdateStatusJSON")
    if json_status is not None:
        json_obj = json.loads(json_status)
        log.debug("JSON status message: {}".format(json_obj))
Esempio n. 15
0
def _enable_replica(instance, suffix):

    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl._ensure_changelog(instance)
    replicas = Replicas(instance)
    replicas.create(properties={
        'cn': 'replica',
        'nsDS5ReplicaRoot': suffix,
        'nsDS5ReplicaId': '1',
        'nsDS5Flags': '1',
        'nsDS5ReplicaType': '3'
        })
Esempio n. 16
0
def test_special_symbol_replica_agreement(topo_i2):
    """ Check if agreement starts with "cn=->..." then
    after upgrade does it get removed.
    
    :id: 68aa0072-4dd4-4e33-b107-cb383a439125
    :setup: two standalone instance
    :steps:
        1. Create and Enable Replication on standalone2 and role as consumer
        2. Create and Enable Replication on standalone1 and role as master
        3. Create a Replication agreement starts with "cn=->..."
        4. Perform an upgrade operation over the master
        5. Check if the agreement is still present or not.
    :expectedresults:
        1. It should be successful
        2. It should be successful
        3. It should be successful
        4. It should be successful
        5. It should be successful
    """

    master = topo_i2.ins["standalone1"]
    consumer = topo_i2.ins["standalone2"]
    consumer.replica.enableReplication(suffix=DEFAULT_SUFFIX,
                                       role=ReplicaRole.CONSUMER,
                                       replicaId=CONSUMER_REPLICAID)
    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl.create_first_master(master)

    properties = {
        RA_NAME: '-\\3meTo_{}:{}'.format(consumer.host, str(consumer.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]
    }

    master.agreement.create(suffix=SUFFIX,
                            host=consumer.host,
                            port=consumer.port,
                            properties=properties)

    master.agreement.init(SUFFIX, consumer.host, consumer.port)

    replica_server = Replicas(master).get(DEFAULT_SUFFIX)

    master.upgrade('online')

    agmt = replica_server.get_agreements().list()[0]

    assert agmt.get_attr_val_utf8('cn') == '-\\3meTo_{}:{}'.format(
        consumer.host, str(consumer.port))
Esempio n. 17
0
def simple_replica(topo, new_suffixes, request):
    """Enable simple multi-supplier replication"""

    supplier1 = topo.ins["standalone1"]
    supplier2 = topo.ins["standalone2"]

    log.info("Enable two supplier replicas")
    replicas_m1 = Replicas(supplier1)
    replica_m1 = replicas_m1.enable(suffix=NEW_SUFFIX,
                                    role=ReplicaRole.SUPPLIER,
                                    replicaID=REPLICA_SUPPLIER_ID)
    replicas_m2 = Replicas(supplier2)
    replica_m2 = replicas_m2.enable(suffix=NEW_SUFFIX,
                                    role=ReplicaRole.SUPPLIER,
                                    replicaID=REPLICA_SUPPLIER_ID + 1)

    log.info("Create agreements between the instances")
    supplier1.agreement.create(suffix=NEW_SUFFIX,
                               host=supplier2.host,
                               port=supplier2.port)
    supplier2.agreement.create(suffix=NEW_SUFFIX,
                               host=supplier1.host,
                               port=supplier1.port)

    log.info("Test replication")
    replicas_m1.test(NEW_SUFFIX, supplier2)

    def fin():
        replicas_m1.disable(NEW_SUFFIX)
        replicas_m2.disable(NEW_SUFFIX)

    request.addfinalizer(fin)

    return [replica_m1, replica_m2]
Esempio n. 18
0
def _compare_memoryruv_and_databaseruv(topo, operation_type):
    """Compare the memoryruv and databaseruv for ldap operations"""

    log.info(
        'Checking memory ruv for ldap: {} operation'.format(operation_type))
    replicas = Replicas(topo.ms['master1'])
    replica = replicas.list()[0]
    memory_ruv = replica.get_attr_val_utf8('nsds50ruv')

    log.info(
        'Checking database ruv for ldap: {} operation'.format(operation_type))
    entry = replicas.get_ruv_entry(DEFAULT_SUFFIX)
    database_ruv = entry.getValues('nsds50ruv')[0]
    assert memory_ruv == database_ruv
Esempio n. 19
0
def test_plugin_bind_dn_tracking_and_replication(topo_m2):
    """Testing nsslapd-plugin-binddn-tracking does not cause issues around
        access control and reconfiguring replication/repl agmt.

    :id: dd689d03-69b8-4bf9-a06e-2acd19d5e2c9
    :setup: 2 supplier topology
    :steps:
        1. Turn on plugin binddn tracking
        2. Add some users
        3. Make an update as a user
        4. Make an update to the replica config
        5. Make an update to the repliocation agreement
    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
    """

    m1 = topo_m2.ms["supplier1"]

    # Turn on bind dn tracking
    m1.config.set('nsslapd-plugin-binddn-tracking', 'on')

    # Add two users
    users = UserAccounts(m1, DEFAULT_SUFFIX)
    user1 = users.create_test_user(uid=1011)
    user1.set('userpassword', PASSWORD)
    user2 = users.create_test_user(uid=1012)

    # Add an aci
    acival = '(targetattr ="cn")(version 3.0;acl "Test bind dn tracking"' + \
             ';allow (all) (userdn = "ldap:///{}");)'.format(user1.dn)
    Domain(m1, DEFAULT_SUFFIX).add('aci', acival)

    # Bind as user and make an update
    user1.rebind(PASSWORD)
    user2.set('cn', 'new value')
    dm = DirectoryManager(m1)
    dm.rebind()

    # modify replica
    replica = Replicas(m1).get(DEFAULT_SUFFIX)
    replica.set(REPL_PROTOCOL_TIMEOUT, "30")

    # modify repl agmt
    agmt = replica.get_agreements().list()[0]
    agmt.set(REPL_PROTOCOL_TIMEOUT, "20")
Esempio n. 20
0
def verify_keepalive_entries(topo, expected):
    # Check that keep alive entries exists (or not exists) for every suppliers on every suppliers
    # Note: The testing method is quite basic: counting that there is one keepalive entry per supplier.
    # that is ok for simple test cases like test_online_init_should_create_keepalive_entries but
    # not for the general case as keep alive associated with no more existing supplier may exists
    # (for example after: db2ldif / demote a supplier / ldif2db / init other suppliers)
    # ==> if the function is somehow pushed in lib389, a check better than simply counting the entries
    # should be done.
    for supplierId in topo.ms:
        supplier = topo.ms[supplierId]
        for replica in Replicas(supplier).list():
            if (replica.get_role() != ReplicaRole.SUPPLIER):
                continue
            replica_info = f'supplier: {supplierId} RID: {replica.get_rid()} suffix: {replica.get_suffix()}'
            log.debug(f'Checking keepAliveEntries on {replica_info}')
            keepaliveEntries = get_keepalive_entries(supplier, replica)
            expectedCount = len(topo.ms) if expected else 0
            foundCount = len(keepaliveEntries)
            if (foundCount == expectedCount):
                log.debug(
                    f'Found {foundCount} keepalive entries as expected on {replica_info}.'
                )
            else:
                log.error(
                    f'{foundCount} Keepalive entries are found '
                    f'while {expectedCount} were expected on {replica_info}.')
                assert False
Esempio n. 21
0
def test_lastupdate_attr_before_init(topo_nr):
    """Check that LastUpdate replica attributes show right values

    :id: bc8ce431-ff65-41f5-9331-605cbcaaa887
    :setup: Replication setup with master and consumer instances
            without initialization
    :steps:
        1. Check nsds5replicaLastUpdateStart value
        2. Check nsds5replicaLastUpdateEnd value
        3. Check nsds5replicaLastUpdateStatus value
    :expectedresults:
        1. nsds5replicaLastUpdateStart should be equal to 0
        2. nsds5replicaLastUpdateEnd should be equal to 0
        3. nsds5replicaLastUpdateStatus should not be equal
           to "0 Replica acquired successfully: Incremental update started"
    """

    master = topo_nr.ins["standalone1"]
    consumer = topo_nr.ins["standalone2"]

    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl.create_first_master(master)

    # Manually create an un-synced consumer.

    consumer_replicas = Replicas(consumer)
    consumer_replicas.create(
        properties={
            'cn': 'replica',
            'nsDS5ReplicaRoot': DEFAULT_SUFFIX,
            'nsDS5ReplicaId': '65535',
            'nsDS5Flags': '0',
            'nsDS5ReplicaType': '2',
        })

    agmt = repl.ensure_agreement(master, consumer)
    with pytest.raises(Exception):
        repl.wait_for_replication(master, consumer, timeout=5)

    assert agmt.get_attr_val_bytes(
        'nsds5replicaLastUpdateStart') == b"19700101000000Z"
    assert agmt.get_attr_val_bytes(
        "nsds5replicaLastUpdateEnd") == b"19700101000000Z"
    assert b"Replica acquired successfully" not in agmt.get_attr_val_bytes(
        "nsds5replicaLastUpdateStatus")
Esempio n. 22
0
def test_invalid_agmt(topo_m2):
    """Test adding that an invalid agreement is properly rejected and does not crash the server

    :id: 6c3b2a7e-edcd-4327-a003-6bd878ff722b
    :setup: Four masters replication setup
    :steps:
        1. Add invalid agreement (nsds5ReplicaEnabled set to invalid value)
        2. Verify the server is still running
    :expectedresults:
        1. Invalid repl agreement should be rejected
        2. Server should be still running
    """

    m1 = topo_m2.ms["master1"]
    m2 = topo_m2.ms["master2"]

    repl = ReplicationManager(DEFAULT_SUFFIX)

    replicas = Replicas(m1)
    replica = replicas.get(DEFAULT_SUFFIX)
    agmts = replica.get_agreements()

    # Add invalid agreement (nsds5ReplicaEnabled set to invalid value)
    with pytest.raises(ldap.UNWILLING_TO_PERFORM):
        agmts.create(
            properties={
                'cn': 'whatever',
                'nsDS5ReplicaRoot': DEFAULT_SUFFIX,
                'nsDS5ReplicaBindDN': 'cn=replication manager,cn=config',
                'nsDS5ReplicaBindMethod': 'simple',
                'nsDS5ReplicaTransportInfo': 'LDAP',
                'nsds5replicaTimeout': '5',
                'description': "test agreement",
                'nsDS5ReplicaHost': m2.host,
                'nsDS5ReplicaPort': str(m2.port),
                'nsDS5ReplicaCredentials': 'whatever',
                'nsds5ReplicaEnabled': 'YEAH MATE, LETS REPLICATE'
            })

    # Verify the server is still running
    repl = ReplicationManager(DEFAULT_SUFFIX)
    repl.test_replication(m1, m2)
    repl.test_replication(m2, m1)
Esempio n. 23
0
 def _lint_cl_trimming(self):
     """Check that cl trimming is at least defined to prevent unbounded growth"""
     suffix = self.get_attr_val_utf8('nsslapd-suffix')
     replicas = Replicas(self._instance)
     replica = replicas.get(suffix)
     bename = self.lint_uid()
     if replica is not None:
         cl = Changelog(self._instance, suffix=suffix)
         try:
             if cl.get_attr_val_utf8('nsslapd-changelogmaxentries') is None and \
                cl.get_attr_val_utf8('nsslapd-changelogmaxage') is None:
                 report = copy.deepcopy(DSCLLE0001)
                 report['fix'] = report['fix'].replace(
                     'YOUR_INSTANCE', self._instance.serverid)
                 report['check'] = f'backends:{bename}::cl_trimming'
                 yield report
         except:
             # No changelog
             pass
Esempio n. 24
0
def check_ruvs(msg, topology_m4, m4rid):
    """Check suppliers 1- 3 for supplier 4's rid."""
    for inst in (topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]):
        clean = False
        replicas = Replicas(inst)
        replica = replicas.get(DEFAULT_SUFFIX)
        log.info('check_ruvs for replica %s:%s (suffix:rid)' % (replica.get_suffix(), replica.get_rid()))

        count = 0
        while not clean and count < 20:
            ruv = replica.get_ruv()
            if m4rid in ruv._rids:
                time.sleep(5)
                count = count + 1
            else:
                clean = True
        if not clean:
            raise Exception("Supplier %s was not cleaned in time." % inst.serverid)
    return True
Esempio n. 25
0
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'
    )
    if ds_supports_new_changelog():
        changelog_dir = topo.ms['supplier1'].get_ldif_dir()
        changelog_end = '_cl.ldif'
    else:
        changelog_dir = topo.ms['supplier1'].get_changelog_dir()
        changelog_end = '.ldif'
    replicas = Replicas(topo.ms["supplier1"])
    replica = replicas.get(DEFAULT_SUFFIX)
    log.info('Remove ldif files, if present in: {}'.format(changelog_dir))
    for files in os.listdir(changelog_dir):
        if files.endswith(changelog_end):
            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')
    replica.begin_task_cl2ldif()

    log.info('Check if changelog ldif file exist in: {}'.format(changelog_dir))
    for files in os.listdir(changelog_dir):
        if files.endswith(changelog_end):
            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
Esempio n. 26
0
def check_ruvs(msg, topology_m4, m4rid):
    """Check masters 1- 3 for master 4's rid."""
    for inst in (topology_m4.ms["master1"], topology_m4.ms["master2"],
                 topology_m4.ms["master3"]):
        clean = False
        replicas = Replicas(inst)
        replica = replicas.get(DEFAULT_SUFFIX)

        count = 0
        while not clean and count < 10:
            ruv = replica.get_ruv()
            if m4rid in ruv._rids:
                time.sleep(5)
                count = count + 1
            else:
                clean = True
        if not clean:
            raise Exception("Master %s was not cleaned in time." %
                            inst.serverid)
    return True
Esempio n. 27
0
 def _lint_cl_trimming(self):
     """Check that cl trimming is at least defined to prevent unbounded growth"""
     bename = self.lint_uid()
     suffix = self.get_attr_val_utf8('nsslapd-suffix')
     replicas = Replicas(self._instance)
     try:
         # Check if replication is enabled
         replicas.get(suffix)
         # Check the changelog
         cl = Changelog(self._instance, suffix=suffix)
         if cl.get_attr_val_utf8('nsslapd-changelogmaxentries') is None and \
            cl.get_attr_val_utf8('nsslapd-changelogmaxage') is None:
             report = copy.deepcopy(DSCLLE0001)
             report['fix'] = report['fix'].replace('YOUR_INSTANCE',
                                                   self._instance.serverid)
             report['check'] = f'backends:{bename}::cl_trimming'
             yield report
     except:
         # Suffix is not replicated
         self._log.debug(
             f"_lint_cl_trimming - backend ({suffix}) is not replicated")
         pass
def test_multiple_changelogs(topo):
    """Test the multiple suffixes can be replicated with the new per backend
    changelog.

    :id: eafcdb57-4ea2-4887-a0a8-9e4d295f4f4d
    :setup: Supplier Instance, Consumer Instance
    :steps:
        1. Create s second suffix
        2. Enable replication for second backend
        3. Perform some updates on both backends and make sure replication is
           working for both backends

    :expectedresults:
        1. Success
        2. Success
        3. Success
    """
    supplier = topo.ms['supplier1']
    consumer = topo.cs['consumer1']

    # Create second suffix dc=second_backend on both replicas
    for inst in [supplier, consumer]:
        # Create the backends
        props = {'cn': 'secondRoot', 'nsslapd-suffix': SECOND_SUFFIX}
        be = Backend(inst)
        be.create(properties=props)
        be.create_sample_entries('001004002')

    # Setup replication for second suffix
    repl = ReplicationManager(SECOND_SUFFIX)
    repl.create_first_supplier(supplier)
    repl.join_consumer(supplier, consumer)

    # Test replication works for each backend
    for suffix in [DEFAULT_SUFFIX, SECOND_SUFFIX]:
        replicas = Replicas(supplier)
        replica = replicas.get(suffix)
        log.info("Testing replication for: " + suffix)
        assert replica.test_replication([consumer])
Esempio n. 29
0
def test_same_attr_yields_same_return_code(topo):
    """Test that various operations with same incorrect attribute value yield same return code
    """
    attr = 'nsDS5ReplicaId'

    replica_reset(topo)
    replicas = Replicas(topo.standalone)
    e = perform_invalid_create(replicas, replica_dict, attr, too_big)
    assert type(e) is ldap.UNWILLING_TO_PERFORM

    replica = replica_setup(topo)
    e = perform_invalid_modify(replica, attr, too_big)
    assert type(e) is ldap.UNWILLING_TO_PERFORM
Esempio n. 30
0
def test_warining_for_invalid_replica(topo_m4):
    """Testing logs to indicate the inconsistency when configuration is performed.

    :id: dd689d03-69b8-4bf9-a06e-2acd19d5e2c8
    :setup: MMR with four masters
    :steps:
        1. Setup nsds5ReplicaBackoffMin to 20
        2. Setup nsds5ReplicaBackoffMax to 10
    :expectedresults:
        1. nsds5ReplicaBackoffMin should set to 20
        2. An error should be generated and also logged in the error logs.
    """
    replicas = Replicas(topo_m4.ms["master1"])
    replica = replicas.list()[0]
    log.info('Set nsds5ReplicaBackoffMin to 20')
    replica.set('nsds5ReplicaBackoffMin', '20')
    with pytest.raises(ldap.UNWILLING_TO_PERFORM):
        log.info('Set nsds5ReplicaBackoffMax to 10')
        replica.set('nsds5ReplicaBackoffMax', '10')
    log.info('Resetting configuration: nsds5ReplicaBackoffMin')
    replica.remove_all('nsds5ReplicaBackoffMin')
    log.info('Check the error log for the error')
    assert topo_m4.ms["master1"].ds_error_log.match(
        '.*nsds5ReplicaBackoffMax.*10.*invalid.*')