Blame SOURCES/0016-Issue-3903-fix-repl-keep-alive-event-interval.patch

0a5078
From 01e941e3eadd7a208982d20c0ca9c104142f2b91 Mon Sep 17 00:00:00 2001
0a5078
From: Mark Reynolds <mreynolds@redhat.com>
0a5078
Date: Wed, 10 Aug 2022 08:58:28 -0400
0a5078
Subject: [PATCH 4/4] Issue 3903 - fix repl keep alive event interval
0a5078
0a5078
Description:  Previously we passed the interval as seconds to the
0a5078
              event queue, but it is supposed to be milliseconds.
0a5078
0a5078
              Fixed a crash with repl logging and decoding extended
0a5078
              op payload (referrals).
0a5078
0a5078
              Also reworked alot of the replication CI tests that
0a5078
              were flaky.
0a5078
0a5078
relates: https://github.com/389ds/389-ds-base/issues/3903
0a5078
0a5078
Reviewed by: tbordaz & spichugi(Thanks!)
0a5078
---
0a5078
 .../suites/replication/acceptance_test.py     |  52 +-
0a5078
 .../cleanallruv_abort_certify_test.py         | 136 ++++
0a5078
 .../cleanallruv_abort_restart_test.py         | 146 ++++
0a5078
 .../replication/cleanallruv_abort_test.py     | 123 +++
0a5078
 .../replication/cleanallruv_force_test.py     | 187 +++++
0a5078
 .../cleanallruv_multiple_force_test.py        | 214 +++++
0a5078
 .../replication/cleanallruv_restart_test.py   | 161 ++++
0a5078
 .../cleanallruv_shutdown_crash_test.py        | 123 +++
0a5078
 .../replication/cleanallruv_stress_test.py    | 216 +++++
0a5078
 .../suites/replication/cleanallruv_test.py    | 742 +-----------------
0a5078
 .../suites/replication/regression_m2_test.py  |  13 +-
0a5078
 .../replication/regression_m2c2_test.py       |   1 +
0a5078
 .../plugins/replication/repl5_replica.c       |  12 +-
0a5078
 ldap/servers/plugins/replication/repl_extop.c |   4 +-
0a5078
 ldap/servers/slapd/task.c                     |   8 +-
0a5078
 src/lib389/lib389/instance/remove.py          |   6 +
0a5078
 16 files changed, 1385 insertions(+), 759 deletions(-)
0a5078
 create mode 100644 dirsrvtests/tests/suites/replication/cleanallruv_abort_certify_test.py
0a5078
 create mode 100644 dirsrvtests/tests/suites/replication/cleanallruv_abort_restart_test.py
0a5078
 create mode 100644 dirsrvtests/tests/suites/replication/cleanallruv_abort_test.py
0a5078
 create mode 100644 dirsrvtests/tests/suites/replication/cleanallruv_force_test.py
0a5078
 create mode 100644 dirsrvtests/tests/suites/replication/cleanallruv_multiple_force_test.py
0a5078
 create mode 100644 dirsrvtests/tests/suites/replication/cleanallruv_restart_test.py
0a5078
 create mode 100644 dirsrvtests/tests/suites/replication/cleanallruv_shutdown_crash_test.py
0a5078
 create mode 100644 dirsrvtests/tests/suites/replication/cleanallruv_stress_test.py
0a5078
0a5078
diff --git a/dirsrvtests/tests/suites/replication/acceptance_test.py b/dirsrvtests/tests/suites/replication/acceptance_test.py
0a5078
index a5f0c4c6b..863ee2553 100644
0a5078
--- a/dirsrvtests/tests/suites/replication/acceptance_test.py
0a5078
+++ b/dirsrvtests/tests/suites/replication/acceptance_test.py
0a5078
@@ -8,6 +8,7 @@
0a5078
 #
0a5078
 import pytest
0a5078
 import logging
0a5078
+import time
0a5078
 from lib389.replica import Replicas
0a5078
 from lib389.tasks import *
0a5078
 from lib389.utils import *
0a5078
@@ -124,12 +125,16 @@ def test_modify_entry(topo_m4, create_entry):
0a5078
         8. Some time should pass
0a5078
         9. The change should be present on all suppliers
0a5078
     """
0a5078
+    if DEBUGGING:
0a5078
+        sleep_time = 8
0a5078
+    else:
0a5078
+        sleep_time = 2
0a5078
 
0a5078
     log.info('Modifying entry {} - add operation'.format(TEST_ENTRY_DN))
0a5078
 
0a5078
     test_user = UserAccount(topo_m4.ms["supplier1"], TEST_ENTRY_DN)
0a5078
     test_user.add('mail', '{}@redhat.com'.format(TEST_ENTRY_NAME))
0a5078
-    time.sleep(1)
0a5078
+    time.sleep(sleep_time)
0a5078
 
0a5078
     all_user = topo_m4.all_get_dsldapobject(TEST_ENTRY_DN, UserAccount)
0a5078
     for u in all_user:
0a5078
@@ -137,7 +142,7 @@ def test_modify_entry(topo_m4, create_entry):
0a5078
 
0a5078
     log.info('Modifying entry {} - replace operation'.format(TEST_ENTRY_DN))
0a5078
     test_user.replace('mail', '{}@greenhat.com'.format(TEST_ENTRY_NAME))
0a5078
-    time.sleep(1)
0a5078
+    time.sleep(sleep_time)
0a5078
 
0a5078
     all_user = topo_m4.all_get_dsldapobject(TEST_ENTRY_DN, UserAccount)
0a5078
     for u in all_user:
0a5078
@@ -145,7 +150,7 @@ def test_modify_entry(topo_m4, create_entry):
0a5078
 
0a5078
     log.info('Modifying entry {} - delete operation'.format(TEST_ENTRY_DN))
0a5078
     test_user.remove('mail', '{}@greenhat.com'.format(TEST_ENTRY_NAME))
0a5078
-    time.sleep(1)
0a5078
+    time.sleep(sleep_time)
0a5078
 
0a5078
     all_user = topo_m4.all_get_dsldapobject(TEST_ENTRY_DN, UserAccount)
0a5078
     for u in all_user:
0a5078
@@ -167,7 +172,10 @@ def test_delete_entry(topo_m4, create_entry):
0a5078
 
0a5078
     log.info('Deleting entry {} during the test'.format(TEST_ENTRY_DN))
0a5078
     topo_m4.ms["supplier1"].delete_s(TEST_ENTRY_DN)
0a5078
-
0a5078
+    if DEBUGGING:
0a5078
+        time.sleep(8)
0a5078
+    else:
0a5078
+        time.sleep(1)
0a5078
     entries = get_repl_entries(topo_m4, TEST_ENTRY_NAME, ["uid"])
0a5078
     assert not entries, "Entry deletion {} wasn't replicated successfully".format(TEST_ENTRY_DN)
0a5078
 
0a5078
@@ -231,6 +239,11 @@ def test_modrdn_after_pause(topo_m4):
0a5078
         5. The change should be present on all suppliers
0a5078
     """
0a5078
 
0a5078
+    if DEBUGGING:
0a5078
+        sleep_time = 8
0a5078
+    else:
0a5078
+        sleep_time = 3
0a5078
+
0a5078
     newrdn_name = 'newrdn'
0a5078
     newrdn_dn = 'uid={},{}'.format(newrdn_name, DEFAULT_SUFFIX)
0a5078
 
0a5078
@@ -264,7 +277,7 @@ def test_modrdn_after_pause(topo_m4):
0a5078
     topo_m4.resume_all_replicas()
0a5078
 
0a5078
     log.info('Wait for replication to happen')
0a5078
-    time.sleep(3)
0a5078
+    time.sleep(sleep_time)
0a5078
 
0a5078
     try:
0a5078
         entries_new = get_repl_entries(topo_m4, newrdn_name, ["uid"])
0a5078
@@ -354,6 +367,11 @@ def test_many_attrs(topo_m4, create_entry):
0a5078
     for add_name in add_list:
0a5078
         test_user.add('description', add_name)
0a5078
 
0a5078
+    if DEBUGGING:
0a5078
+        time.sleep(10)
0a5078
+    else:
0a5078
+        time.sleep(1)
0a5078
+
0a5078
     log.info('Check that everything was properly replicated after an add operation')
0a5078
     entries = get_repl_entries(topo_m4, TEST_ENTRY_NAME, ["description"])
0a5078
     for entry in entries:
0a5078
@@ -363,6 +381,11 @@ def test_many_attrs(topo_m4, create_entry):
0a5078
     for delete_name in delete_list:
0a5078
         test_user.remove('description', delete_name)
0a5078
 
0a5078
+    if DEBUGGING:
0a5078
+        time.sleep(10)
0a5078
+    else:
0a5078
+        time.sleep(1)
0a5078
+
0a5078
     log.info('Check that everything was properly replicated after a delete operation')
0a5078
     entries = get_repl_entries(topo_m4, TEST_ENTRY_NAME, ["description"])
0a5078
     for entry in entries:
0a5078
@@ -386,12 +409,22 @@ def test_double_delete(topo_m4, create_entry):
0a5078
     log.info('Deleting entry {} from supplier1'.format(TEST_ENTRY_DN))
0a5078
     topo_m4.ms["supplier1"].delete_s(TEST_ENTRY_DN)
0a5078
 
0a5078
+    if DEBUGGING:
0a5078
+        time.sleep(5)
0a5078
+    else:
0a5078
+        time.sleep(1)
0a5078
+
0a5078
     log.info('Deleting entry {} from supplier2'.format(TEST_ENTRY_DN))
0a5078
     try:
0a5078
         topo_m4.ms["supplier2"].delete_s(TEST_ENTRY_DN)
0a5078
     except ldap.NO_SUCH_OBJECT:
0a5078
         log.info("Entry {} wasn't found supplier2. It is expected.".format(TEST_ENTRY_DN))
0a5078
 
0a5078
+    if DEBUGGING:
0a5078
+        time.sleep(5)
0a5078
+    else:
0a5078
+        time.sleep(1)
0a5078
+        
0a5078
     log.info('Make searches to check if server is alive')
0a5078
     entries = get_repl_entries(topo_m4, TEST_ENTRY_NAME, ["uid"])
0a5078
     assert not entries, "Entry deletion {} wasn't replicated successfully".format(TEST_ENTRY_DN)
0a5078
@@ -436,6 +469,11 @@ def test_password_repl_error(topo_m4, create_entry):
0a5078
     m3_conn = test_user_m3.bind(TEST_ENTRY_NEW_PASS)
0a5078
     m4_conn = test_user_m4.bind(TEST_ENTRY_NEW_PASS)
0a5078
 
0a5078
+    if DEBUGGING:
0a5078
+        time.sleep(5)
0a5078
+    else:
0a5078
+        time.sleep(1)
0a5078
+
0a5078
     log.info('Check the error log for the error with {}'.format(TEST_ENTRY_DN))
0a5078
     assert not m2.ds_error_log.match('.*can.t add a change for uid={}.*'.format(TEST_ENTRY_NAME))
0a5078
 
0a5078
@@ -552,7 +590,7 @@ def test_csnpurge_large_valueset(topo_m2):
0a5078
     replica = replicas.list()[0]
0a5078
     log.info('nsds5ReplicaPurgeDelay to 5')
0a5078
     replica.set('nsds5ReplicaPurgeDelay', '5')
0a5078
-    time.sleep(6)
0a5078
+    time.sleep(10)
0a5078
 
0a5078
     # add some new values to the valueset containing entries that should be purged
0a5078
     for i in range(21,25):
0a5078
@@ -612,7 +650,7 @@ def test_urp_trigger_substring_search(topo_m2):
0a5078
             break
0a5078
         else:
0a5078
             log.info('Entry not yet replicated on M2, wait a bit')
0a5078
-            time.sleep(2)
0a5078
+            time.sleep(3)
0a5078
 
0a5078
     # check that M2 access logs does not "(&(objectclass=nstombstone)(nscpentrydn=uid=asterisk_*_in_value,dc=example,dc=com))"
0a5078
     log.info('Check that on M2, URP as not triggered such internal search')
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_abort_certify_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_abort_certify_test.py
0a5078
new file mode 100644
0a5078
index 000000000..603693b9e
0a5078
--- /dev/null
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_abort_certify_test.py
0a5078
@@ -0,0 +1,136 @@
0a5078
+# --- BEGIN COPYRIGHT BLOCK ---
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
+# All rights reserved.
0a5078
+#
0a5078
+# License: GPL (version 3 or any later version).
0a5078
+# See LICENSE for details.
0a5078
+# --- END COPYRIGHT BLOCK ---
0a5078
+#
0a5078
+import logging
0a5078
+import pytest
0a5078
+import os
0a5078
+import time
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
+from lib389.topologies import topology_m4
0a5078
+from lib389.tasks import CleanAllRUVTask
0a5078
+from lib389.replica import ReplicationManager, Replicas
0a5078
+
0a5078
+log = logging.getLogger(__name__)
0a5078
+
0a5078
+
0a5078
+def remove_supplier4_agmts(msg, topology_m4):
0a5078
+    """Remove all the repl agmts to supplier4. """
0a5078
+
0a5078
+    log.info('%s: remove all the agreements to supplier 4...' % msg)
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    # This will delete m4 from the topo *and* remove all incoming agreements
0a5078
+    # to m4.
0a5078
+    repl.remove_supplier(topology_m4.ms["supplier4"],
0a5078
+        [topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]])
0a5078
+
0a5078
+def task_done(topology_m4, task_dn, timeout=60):
0a5078
+    """Check if the task is complete"""
0a5078
+
0a5078
+    attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode',
0a5078
+                'nsTaskCurrentItem', 'nsTaskTotalItems']
0a5078
+    done = False
0a5078
+    count = 0
0a5078
+
0a5078
+    while not done and count < timeout:
0a5078
+        try:
0a5078
+            entry = topology_m4.ms["supplier1"].getEntry(task_dn, attrlist=attrlist)
0a5078
+            if entry is not None:
0a5078
+                if entry.hasAttr('nsTaskExitCode'):
0a5078
+                    done = True
0a5078
+                    break
0a5078
+            else:
0a5078
+                done = True
0a5078
+                break
0a5078
+        except ldap.NO_SUCH_OBJECT:
0a5078
+            done = True
0a5078
+            break
0a5078
+        except ldap.LDAPError:
0a5078
+            break
0a5078
+        time.sleep(1)
0a5078
+        count += 1
0a5078
+
0a5078
+    return done
0a5078
+
0a5078
+@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
+def test_abort_certify(topology_m4):
0a5078
+    """Test the abort task with a replica-certify-all option
0a5078
+
0a5078
+    :id: 78959966-d644-44a8-b98c-1fcf21b45eb0
0a5078
+    :setup: Replication setup with four suppliers
0a5078
+    :steps:
0a5078
+        1. Disable replication on supplier 4
0a5078
+        2. Remove agreements to supplier 4 from other suppliers
0a5078
+        3. Stop supplier 2
0a5078
+        4. Run a cleanallruv task on supplier 1
0a5078
+        5. Run a cleanallruv abort task on supplier 1 with a replica-certify-all option
0a5078
+    :expectedresults: No hanging tasks left
0a5078
+        1. Replication on supplier 4 should be disabled
0a5078
+        2. Agreements to supplier 4 should be removed
0a5078
+        3. Supplier 2 should be stopped
0a5078
+        4. Operation should be successful
0a5078
+        5. Operation should be successful
0a5078
+    """
0a5078
+
0a5078
+    log.info('Running test_abort_certify...')
0a5078
+
0a5078
+    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
+    remove_supplier4_agmts("test_abort_certify", topology_m4)
0a5078
+
0a5078
+    # Stop supplier 2
0a5078
+    log.info('test_abort_certify: stop supplier 2 to freeze the cleanAllRUV task...')
0a5078
+    topology_m4.ms["supplier2"].stop()
0a5078
+
0a5078
+    # Run the task
0a5078
+    log.info('test_abort_certify: add the cleanAllRUV task...')
0a5078
+    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
+    cruv_task.create(properties={
0a5078
+        'replica-id': m4rid,
0a5078
+        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+        'replica-force-cleaning': 'no',
0a5078
+        'replica-certify-all': 'yes'
0a5078
+        })
0a5078
+    # Wait a bit
0a5078
+    time.sleep(2)
0a5078
+
0a5078
+    # Abort the task
0a5078
+    log.info('test_abort_certify: abort the cleanAllRUV task...')
0a5078
+    abort_task = cruv_task.abort(certify=True)
0a5078
+
0a5078
+    # Wait a while and make sure the abort task is still running
0a5078
+    log.info('test_abort_certify...')
0a5078
+
0a5078
+    if task_done(topology_m4, abort_task.dn, 10):
0a5078
+        log.fatal('test_abort_certify: abort task incorrectly finished')
0a5078
+        assert False
0a5078
+
0a5078
+    # Now start supplier 2 so it can be aborted
0a5078
+    log.info('test_abort_certify: start supplier 2 to allow the abort task to finish...')
0a5078
+    topology_m4.ms["supplier2"].start()
0a5078
+
0a5078
+    # Wait for the abort task to stop
0a5078
+    if not task_done(topology_m4, abort_task.dn, 90):
0a5078
+        log.fatal('test_abort_certify: The abort CleanAllRUV task was not aborted')
0a5078
+        assert False
0a5078
+
0a5078
+    # Check supplier 1 does not have the clean task running
0a5078
+    log.info('test_abort_certify: check supplier 1 no longer has a cleanAllRUV task...')
0a5078
+    if not task_done(topology_m4, cruv_task.dn):
0a5078
+        log.fatal('test_abort_certify: CleanAllRUV task was not aborted')
0a5078
+        assert False
0a5078
+
0a5078
+    log.info('test_abort_certify PASSED')
0a5078
+
0a5078
+
0a5078
+if __name__ == '__main__':
0a5078
+    # Run isolated
0a5078
+    # -s for DEBUG mode
0a5078
+    CURRENT_FILE = os.path.realpath(__file__)
0a5078
+    pytest.main(["-s", CURRENT_FILE])
0a5078
+
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_abort_restart_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_abort_restart_test.py
0a5078
new file mode 100644
0a5078
index 000000000..1406c6553
0a5078
--- /dev/null
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_abort_restart_test.py
0a5078
@@ -0,0 +1,146 @@
0a5078
+# --- BEGIN COPYRIGHT BLOCK ---
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
+# All rights reserved.
0a5078
+#
0a5078
+# License: GPL (version 3 or any later version).
0a5078
+# See LICENSE for details.
0a5078
+# --- END COPYRIGHT BLOCK ---
0a5078
+#
0a5078
+import logging
0a5078
+import pytest
0a5078
+import os
0a5078
+import time
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
+from lib389.topologies import topology_m4
0a5078
+from lib389.tasks import CleanAllRUVTask
0a5078
+from lib389.replica import ReplicationManager
0a5078
+
0a5078
+log = logging.getLogger(__name__)
0a5078
+
0a5078
+
0a5078
+def remove_supplier4_agmts(msg, topology_m4):
0a5078
+    """Remove all the repl agmts to supplier4. """
0a5078
+
0a5078
+    log.info('%s: remove all the agreements to supplier 4...' % msg)
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    # This will delete m4 from the topo *and* remove all incoming agreements
0a5078
+    # to m4.
0a5078
+    repl.remove_supplier(topology_m4.ms["supplier4"],
0a5078
+        [topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]])
0a5078
+
0a5078
+def task_done(topology_m4, task_dn, timeout=60):
0a5078
+    """Check if the task is complete"""
0a5078
+
0a5078
+    attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode',
0a5078
+                'nsTaskCurrentItem', 'nsTaskTotalItems']
0a5078
+    done = False
0a5078
+    count = 0
0a5078
+
0a5078
+    while not done and count < timeout:
0a5078
+        try:
0a5078
+            entry = topology_m4.ms["supplier1"].getEntry(task_dn, attrlist=attrlist)
0a5078
+            if entry is not None:
0a5078
+                if entry.hasAttr('nsTaskExitCode'):
0a5078
+                    done = True
0a5078
+                    break
0a5078
+            else:
0a5078
+                done = True
0a5078
+                break
0a5078
+        except ldap.NO_SUCH_OBJECT:
0a5078
+            done = True
0a5078
+            break
0a5078
+        except ldap.LDAPError:
0a5078
+            break
0a5078
+        time.sleep(1)
0a5078
+        count += 1
0a5078
+
0a5078
+    return done
0a5078
+   
0a5078
+
0a5078
+@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
+def test_abort_restart(topology_m4):
0a5078
+    """Test the abort task can handle a restart, and then resume
0a5078
+
0a5078
+    :id: b66e33d4-fe85-4e1c-b882-75da80f70ab3
0a5078
+    :setup: Replication setup with four suppliers
0a5078
+    :steps:
0a5078
+        1. Disable replication on supplier 4
0a5078
+        2. Remove agreements to supplier 4 from other suppliers
0a5078
+        3. Stop supplier 3
0a5078
+        4. Run a cleanallruv task on supplier 1
0a5078
+        5. Run a cleanallruv abort task on supplier 1
0a5078
+        6. Restart supplier 1
0a5078
+        7. Make sure that no crash happened
0a5078
+        8. Start supplier 3
0a5078
+        9. Check supplier 1 does not have the clean task running
0a5078
+        10. Check that errors log doesn't have 'Aborting abort task' message
0a5078
+    :expectedresults:
0a5078
+        1. Replication on supplier 4 should be disabled
0a5078
+        2. Agreements to supplier 4 should be removed
0a5078
+        3. Supplier 3 should be stopped
0a5078
+        4. Operation should be successful
0a5078
+        5. Operation should be successful
0a5078
+        6. Supplier 1 should be restarted
0a5078
+        7. No crash should happened
0a5078
+        8. Supplier 3 should be started
0a5078
+        9. Check supplier 1 shouldn't have the clean task running
0a5078
+        10. Errors log shouldn't have 'Aborting abort task' message
0a5078
+    """
0a5078
+
0a5078
+    log.info('Running test_abort_restart...')
0a5078
+    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
+    remove_supplier4_agmts("test_abort", topology_m4)
0a5078
+
0a5078
+    # Stop supplier 3
0a5078
+    log.info('test_abort_restart: stop supplier 3 to freeze the cleanAllRUV task...')
0a5078
+    topology_m4.ms["supplier3"].stop()
0a5078
+
0a5078
+    # Run the task
0a5078
+    log.info('test_abort_restart: add the cleanAllRUV task...')
0a5078
+    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
+    cruv_task.create(properties={
0a5078
+        'replica-id': m4rid,
0a5078
+        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+        'replica-force-cleaning': 'no',
0a5078
+        'replica-certify-all': 'yes'
0a5078
+        })
0a5078
+    # Wait a bit
0a5078
+    time.sleep(2)
0a5078
+
0a5078
+    # Abort the task
0a5078
+    cruv_task.abort(certify=True)
0a5078
+
0a5078
+    # Check supplier 1 does not have the clean task running
0a5078
+    log.info('test_abort_abort: check supplier 1 no longer has a cleanAllRUV task...')
0a5078
+    if not task_done(topology_m4, cruv_task.dn):
0a5078
+        log.fatal('test_abort_restart: CleanAllRUV task was not aborted')
0a5078
+        assert False
0a5078
+
0a5078
+    # Now restart supplier 1, and make sure the abort process completes
0a5078
+    topology_m4.ms["supplier1"].restart()
0a5078
+    if topology_m4.ms["supplier1"].detectDisorderlyShutdown():
0a5078
+        log.fatal('test_abort_restart: Supplier 1 previously crashed!')
0a5078
+        assert False
0a5078
+
0a5078
+    # Start supplier 3
0a5078
+    topology_m4.ms["supplier3"].start()
0a5078
+
0a5078
+    # Need to wait 5 seconds before server processes any leftover tasks
0a5078
+    time.sleep(6)
0a5078
+
0a5078
+    # Check supplier 1 tried to run abort task.  We expect the abort task to be aborted.
0a5078
+    if not topology_m4.ms["supplier1"].searchErrorsLog('Aborting abort task'):
0a5078
+        log.fatal('test_abort_restart: Abort task did not restart')
0a5078
+        assert False
0a5078
+
0a5078
+    log.info('test_abort_restart PASSED')
0a5078
+    
0a5078
+
0a5078
+if __name__ == '__main__':
0a5078
+    # Run isolated
0a5078
+    # -s for DEBUG mode
0a5078
+    CURRENT_FILE = os.path.realpath(__file__)
0a5078
+    pytest.main(["-s", CURRENT_FILE])
0a5078
+
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_abort_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_abort_test.py
0a5078
new file mode 100644
0a5078
index 000000000..f89188165
0a5078
--- /dev/null
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_abort_test.py
0a5078
@@ -0,0 +1,123 @@
0a5078
+# --- BEGIN COPYRIGHT BLOCK ---
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
+# All rights reserved.
0a5078
+#
0a5078
+# License: GPL (version 3 or any later version).
0a5078
+# See LICENSE for details.
0a5078
+# --- END COPYRIGHT BLOCK ---
0a5078
+#
0a5078
+import logging
0a5078
+import pytest
0a5078
+import os
0a5078
+import time
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
+from lib389.topologies import topology_m4
0a5078
+from lib389.tasks import CleanAllRUVTask
0a5078
+from lib389.replica import ReplicationManager
0a5078
+
0a5078
+log = logging.getLogger(__name__)
0a5078
+
0a5078
+
0a5078
+def remove_supplier4_agmts(msg, topology_m4):
0a5078
+    """Remove all the repl agmts to supplier4. """
0a5078
+
0a5078
+    log.info('%s: remove all the agreements to supplier 4...' % msg)
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    # This will delete m4 from the topo *and* remove all incoming agreements
0a5078
+    # to m4.
0a5078
+    repl.remove_supplier(topology_m4.ms["supplier4"],
0a5078
+        [topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]])
0a5078
+
0a5078
+def task_done(topology_m4, task_dn, timeout=60):
0a5078
+    """Check if the task is complete"""
0a5078
+
0a5078
+    attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode',
0a5078
+                'nsTaskCurrentItem', 'nsTaskTotalItems']
0a5078
+    done = False
0a5078
+    count = 0
0a5078
+
0a5078
+    while not done and count < timeout:
0a5078
+        try:
0a5078
+            entry = topology_m4.ms["supplier1"].getEntry(task_dn, attrlist=attrlist)
0a5078
+            if entry is not None:
0a5078
+                if entry.hasAttr('nsTaskExitCode'):
0a5078
+                    done = True
0a5078
+                    break
0a5078
+            else:
0a5078
+                done = True
0a5078
+                break
0a5078
+        except ldap.NO_SUCH_OBJECT:
0a5078
+            done = True
0a5078
+            break
0a5078
+        except ldap.LDAPError:
0a5078
+            break
0a5078
+        time.sleep(1)
0a5078
+        count += 1
0a5078
+
0a5078
+    return done
0a5078
+
0a5078
+    
0a5078
+@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
+def test_abort(topology_m4):
0a5078
+    """Test the abort task basic functionality
0a5078
+
0a5078
+    :id: b09a6887-8de0-4fac-8e41-73ccbaaf7a08
0a5078
+    :setup: Replication setup with four suppliers
0a5078
+    :steps:
0a5078
+        1. Disable replication on supplier 4
0a5078
+        2. Remove agreements to supplier 4 from other suppliers
0a5078
+        3. Stop supplier 2
0a5078
+        4. Run a cleanallruv task on supplier 1
0a5078
+        5. Run a cleanallruv abort task on supplier 1
0a5078
+    :expectedresults: No hanging tasks left
0a5078
+        1. Replication on supplier 4 should be disabled
0a5078
+        2. Agreements to supplier 4 should be removed
0a5078
+        3. Supplier 2 should be stopped
0a5078
+        4. Operation should be successful
0a5078
+        5. Operation should be successful
0a5078
+    """
0a5078
+
0a5078
+    log.info('Running test_abort...')
0a5078
+    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
+    remove_supplier4_agmts("test_abort", topology_m4)
0a5078
+
0a5078
+    # Stop supplier 2
0a5078
+    log.info('test_abort: stop supplier 2 to freeze the cleanAllRUV task...')
0a5078
+    topology_m4.ms["supplier2"].stop()
0a5078
+
0a5078
+    # Run the task
0a5078
+    log.info('test_abort: add the cleanAllRUV task...')
0a5078
+    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
+    cruv_task.create(properties={
0a5078
+        'replica-id': m4rid,
0a5078
+        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+        'replica-force-cleaning': 'no',
0a5078
+        'replica-certify-all': 'yes'
0a5078
+        })
0a5078
+    # Wait a bit
0a5078
+    time.sleep(2)
0a5078
+
0a5078
+    # Abort the task
0a5078
+    cruv_task.abort()
0a5078
+
0a5078
+    # Check supplier 1 does not have the clean task running
0a5078
+    log.info('test_abort: check supplier 1 no longer has a cleanAllRUV task...')
0a5078
+    if not task_done(topology_m4, cruv_task.dn):
0a5078
+        log.fatal('test_abort: CleanAllRUV task was not aborted')
0a5078
+        assert False
0a5078
+
0a5078
+    # Start supplier 2
0a5078
+    log.info('test_abort: start supplier 2 to begin the restore process...')
0a5078
+    topology_m4.ms["supplier2"].start()
0a5078
+
0a5078
+    log.info('test_abort PASSED')
0a5078
+
0a5078
+
0a5078
+if __name__ == '__main__':
0a5078
+    # Run isolated
0a5078
+    # -s for DEBUG mode
0a5078
+    CURRENT_FILE = os.path.realpath(__file__)
0a5078
+    pytest.main(["-s", CURRENT_FILE])
0a5078
+
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_force_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_force_test.py
0a5078
new file mode 100644
0a5078
index 000000000..d5b930584
0a5078
--- /dev/null
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_force_test.py
0a5078
@@ -0,0 +1,187 @@
0a5078
+# --- BEGIN COPYRIGHT BLOCK ---
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
+# All rights reserved.
0a5078
+#
0a5078
+# License: GPL (version 3 or any later version).
0a5078
+# See LICENSE for details.
0a5078
+# --- END COPYRIGHT BLOCK ---
0a5078
+#
0a5078
+import logging
0a5078
+import pytest
0a5078
+import os
0a5078
+import time
0a5078
+import random
0a5078
+import threading
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
+from lib389.topologies import topology_m4
0a5078
+from lib389.tasks import CleanAllRUVTask
0a5078
+from lib389.replica import Replicas, ReplicationManager
0a5078
+from lib389.idm.directorymanager import DirectoryManager
0a5078
+from lib389.idm.user import UserAccounts
0a5078
+
0a5078
+log = logging.getLogger(__name__)
0a5078
+
0a5078
+
0a5078
+class AddUsers(threading.Thread):
0a5078
+    def __init__(self, inst, num_users):
0a5078
+        threading.Thread.__init__(self)
0a5078
+        self.daemon = True
0a5078
+        self.inst = inst
0a5078
+        self.num_users = num_users
0a5078
+
0a5078
+    def run(self):
0a5078
+        """Start adding users"""
0a5078
+
0a5078
+        dm = DirectoryManager(self.inst)
0a5078
+        conn = dm.bind()
0a5078
+
0a5078
+        users = UserAccounts(conn, DEFAULT_SUFFIX)
0a5078
+
0a5078
+        u_range = list(range(self.num_users))
0a5078
+        random.shuffle(u_range)
0a5078
+
0a5078
+        for idx in u_range:
0a5078
+            try:
0a5078
+                users.create(properties={
0a5078
+                    'uid': 'testuser%s' % idx,
0a5078
+                    'cn' : 'testuser%s' % idx,
0a5078
+                    'sn' : 'user%s' % idx,
0a5078
+                    'uidNumber' : '%s' % (1000 + idx),
0a5078
+                    'gidNumber' : '%s' % (1000 + idx),
0a5078
+                    'homeDirectory' : '/home/testuser%s' % idx
0a5078
+                })
0a5078
+            # One of the suppliers was probably put into read only mode - just break out
0a5078
+            except ldap.UNWILLING_TO_PERFORM:
0a5078
+                break
0a5078
+            except ldap.ALREADY_EXISTS:
0a5078
+                pass
0a5078
+        conn.close()
0a5078
+
0a5078
+def remove_some_supplier4_agmts(msg, topology_m4):
0a5078
+    """Remove all the repl agmts to supplier4 except from supplier3.  Used by
0a5078
+    the force tests."""
0a5078
+
0a5078
+    log.info('%s: remove the agreements to supplier 4...' % msg)
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    # This will delete m4 from the topo *and* remove all incoming agreements
0a5078
+    # to m4.
0a5078
+    repl.remove_supplier(topology_m4.ms["supplier4"],
0a5078
+        [topology_m4.ms["supplier1"], topology_m4.ms["supplier2"]])
0a5078
+
0a5078
+def task_done(topology_m4, task_dn, timeout=60):
0a5078
+    """Check if the task is complete"""
0a5078
+
0a5078
+    attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode',
0a5078
+                'nsTaskCurrentItem', 'nsTaskTotalItems']
0a5078
+    done = False
0a5078
+    count = 0
0a5078
+
0a5078
+    while not done and count < timeout:
0a5078
+        try:
0a5078
+            entry = topology_m4.ms["supplier1"].getEntry(task_dn, attrlist=attrlist)
0a5078
+            if entry is not None:
0a5078
+                if entry.hasAttr('nsTaskExitCode'):
0a5078
+                    done = True
0a5078
+                    break
0a5078
+            else:
0a5078
+                done = True
0a5078
+                break
0a5078
+        except ldap.NO_SUCH_OBJECT:
0a5078
+            done = True
0a5078
+            break
0a5078
+        except ldap.LDAPError:
0a5078
+            break
0a5078
+        time.sleep(1)
0a5078
+        count += 1
0a5078
+
0a5078
+    return done
0a5078
+
0a5078
+def check_ruvs(msg, topology_m4, m4rid):
0a5078
+    """Check suppliers 1-3 for supplier 4's rid."""
0a5078
+    for inst in (topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]):
0a5078
+        clean = False
0a5078
+        replicas = Replicas(inst)
0a5078
+        replica = replicas.get(DEFAULT_SUFFIX)
0a5078
+        log.info('check_ruvs for replica %s:%s (suffix:rid)' % (replica.get_suffix(), replica.get_rid()))
0a5078
+
0a5078
+        count = 0
0a5078
+        while not clean and count < 20:
0a5078
+            ruv = replica.get_ruv()
0a5078
+            if m4rid in ruv._rids:
0a5078
+                time.sleep(5)
0a5078
+                count = count + 1
0a5078
+            else:
0a5078
+                clean = True
0a5078
+        if not clean:
0a5078
+            raise Exception("Supplier %s was not cleaned in time." % inst.serverid)
0a5078
+    return True
0a5078
+
0a5078
+def test_clean_force(topology_m4):
0a5078
+    """Check that multiple tasks with a 'force' option work properly
0a5078
+
0a5078
+    :id: f8810dfe-d2d2-4dd9-ba03-5fc14896fabe
0a5078
+    :setup: Replication setup with four suppliers
0a5078
+    :steps:
0a5078
+        1. Stop supplier 3
0a5078
+        2. Add a bunch of updates to supplier 4
0a5078
+        3. Disable replication on supplier 4
0a5078
+        4. Start supplier 3
0a5078
+        5. Remove agreements to supplier 4 from other suppliers
0a5078
+        6. Run a cleanallruv task on supplier 1 with a 'force' option 'on'
0a5078
+        7. Check that everything was cleaned
0a5078
+    :expectedresults:
0a5078
+        1. Supplier 3 should be stopped
0a5078
+        2. Operation should be successful
0a5078
+        3. Replication on supplier 4 should be disabled
0a5078
+        4. Supplier 3 should be started
0a5078
+        5. Agreements to supplier 4 should be removed
0a5078
+        6. Operation should be successful
0a5078
+        7. Everything should be cleaned
0a5078
+    """
0a5078
+
0a5078
+    log.info('Running test_clean_force...')
0a5078
+
0a5078
+    # Stop supplier 3, while we update supplier 4, so that 3 is behind the other suppliers
0a5078
+    topology_m4.ms["supplier3"].stop()
0a5078
+
0a5078
+    # Add a bunch of updates to supplier 4
0a5078
+    m4_add_users = AddUsers(topology_m4.ms["supplier4"], 10)
0a5078
+    m4_add_users.start()
0a5078
+    m4_add_users.join()
0a5078
+
0a5078
+    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
+    remove_some_supplier4_agmts("test_clean_force", topology_m4)
0a5078
+
0a5078
+    # Start supplier 3, it should be out of sync with the other replicas...
0a5078
+    topology_m4.ms["supplier3"].start()
0a5078
+
0a5078
+    # Remove the agreement to replica 4
0a5078
+    replica = Replicas(topology_m4.ms["supplier3"]).get(DEFAULT_SUFFIX)
0a5078
+    replica.get_agreements().get("004").delete()
0a5078
+
0a5078
+    # Run the task, use "force" because supplier 3 is not in sync with the other replicas
0a5078
+    # in regards to the replica 4 RUV
0a5078
+    log.info('test_clean: run the cleanAllRUV task...')
0a5078
+    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
+    cruv_task.create(properties={
0a5078
+        'replica-id': m4rid,
0a5078
+        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+        'replica-force-cleaning': 'yes'
0a5078
+        })
0a5078
+    cruv_task.wait()
0a5078
+
0a5078
+    # Check the other supplier's RUV for 'replica 4'
0a5078
+    log.info('test_clean_force: check all the suppliers have been cleaned...')
0a5078
+    clean = check_ruvs("test_clean_force", topology_m4, m4rid)
0a5078
+    assert clean
0a5078
+
0a5078
+    log.info('test_clean_force PASSED')
0a5078
+
0a5078
+
0a5078
+if __name__ == '__main__':
0a5078
+    # Run isolated
0a5078
+    # -s for DEBUG mode
0a5078
+    CURRENT_FILE = os.path.realpath(__file__)
0a5078
+    pytest.main(["-s", CURRENT_FILE])
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_multiple_force_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_multiple_force_test.py
0a5078
new file mode 100644
0a5078
index 000000000..0a0848bda
0a5078
--- /dev/null
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_multiple_force_test.py
0a5078
@@ -0,0 +1,214 @@
0a5078
+# --- BEGIN COPYRIGHT BLOCK ---
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
+# All rights reserved.
0a5078
+#
0a5078
+# License: GPL (version 3 or any later version).
0a5078
+# See LICENSE for details.
0a5078
+# --- END COPYRIGHT BLOCK ---
0a5078
+#
0a5078
+import ldap
0a5078
+import logging
0a5078
+import os
0a5078
+import pytest
0a5078
+import random
0a5078
+import time
0a5078
+import threading
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
+from lib389.topologies import topology_m4
0a5078
+from lib389.tasks import CleanAllRUVTask
0a5078
+from lib389.idm.directorymanager import DirectoryManager
0a5078
+from lib389.idm.user import UserAccounts
0a5078
+from lib389.replica import ReplicationManager, Replicas
0a5078
+
0a5078
+log = logging.getLogger(__name__)
0a5078
+
0a5078
+
0a5078
+class AddUsers(threading.Thread):
0a5078
+    def __init__(self, inst, num_users):
0a5078
+        threading.Thread.__init__(self)
0a5078
+        self.daemon = True
0a5078
+        self.inst = inst
0a5078
+        self.num_users = num_users
0a5078
+
0a5078
+    def run(self):
0a5078
+        """Start adding users"""
0a5078
+
0a5078
+        dm = DirectoryManager(self.inst)
0a5078
+        conn = dm.bind()
0a5078
+
0a5078
+        users = UserAccounts(conn, DEFAULT_SUFFIX)
0a5078
+
0a5078
+        u_range = list(range(self.num_users))
0a5078
+        random.shuffle(u_range)
0a5078
+
0a5078
+        for idx in u_range:
0a5078
+            try:
0a5078
+                users.create(properties={
0a5078
+                    'uid': 'testuser%s' % idx,
0a5078
+                    'cn' : 'testuser%s' % idx,
0a5078
+                    'sn' : 'user%s' % idx,
0a5078
+                    'uidNumber' : '%s' % (1000 + idx),
0a5078
+                    'gidNumber' : '%s' % (1000 + idx),
0a5078
+                    'homeDirectory' : '/home/testuser%s' % idx
0a5078
+                })
0a5078
+            # One of the suppliers was probably put into read only mode - just break out
0a5078
+            except ldap.UNWILLING_TO_PERFORM:
0a5078
+                break
0a5078
+            except ldap.ALREADY_EXISTS:
0a5078
+                pass
0a5078
+        conn.close()
0a5078
+
0a5078
+def remove_some_supplier4_agmts(msg, topology_m4):
0a5078
+    """Remove all the repl agmts to supplier4 except from supplier3.  Used by
0a5078
+    the force tests."""
0a5078
+
0a5078
+    log.info('%s: remove the agreements to supplier 4...' % msg)
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    # This will delete m4 from the topo *and* remove all incoming agreements
0a5078
+    # to m4.
0a5078
+    repl.remove_supplier(topology_m4.ms["supplier4"],
0a5078
+        [topology_m4.ms["supplier1"], topology_m4.ms["supplier2"]])
0a5078
+
0a5078
+def task_done(topology_m4, task_dn, timeout=60):
0a5078
+    """Check if the task is complete"""
0a5078
+
0a5078
+    attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode',
0a5078
+                'nsTaskCurrentItem', 'nsTaskTotalItems']
0a5078
+    done = False
0a5078
+    count = 0
0a5078
+
0a5078
+    while not done and count < timeout:
0a5078
+        try:
0a5078
+            entry = topology_m4.ms["supplier1"].getEntry(task_dn, attrlist=attrlist)
0a5078
+            if entry is not None:
0a5078
+                if entry.hasAttr('nsTaskExitCode'):
0a5078
+                    done = True
0a5078
+                    break
0a5078
+            else:
0a5078
+                done = True
0a5078
+                break
0a5078
+        except ldap.NO_SUCH_OBJECT:
0a5078
+            done = True
0a5078
+            break
0a5078
+        except ldap.LDAPError:
0a5078
+            break
0a5078
+        time.sleep(1)
0a5078
+        count += 1
0a5078
+
0a5078
+    return done
0a5078
+
0a5078
+def check_ruvs(msg, topology_m4, m4rid):
0a5078
+    """Check suppliers 1-3 for supplier 4's rid."""
0a5078
+    for inst in (topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]):
0a5078
+        clean = False
0a5078
+        replicas = Replicas(inst)
0a5078
+        replica = replicas.get(DEFAULT_SUFFIX)
0a5078
+        log.info('check_ruvs for replica %s:%s (suffix:rid)' % (replica.get_suffix(), replica.get_rid()))
0a5078
+
0a5078
+        count = 0
0a5078
+        while not clean and count < 20:
0a5078
+            ruv = replica.get_ruv()
0a5078
+            if m4rid in ruv._rids:
0a5078
+                time.sleep(5)
0a5078
+                count = count + 1
0a5078
+            else:
0a5078
+                clean = True
0a5078
+        if not clean:
0a5078
+            raise Exception("Supplier %s was not cleaned in time." % inst.serverid)
0a5078
+    return True
0a5078
+
0a5078
+
0a5078
+def test_multiple_tasks_with_force(topology_m4):
0a5078
+    """Check that multiple tasks with a 'force' option work properly
0a5078
+
0a5078
+    :id: eb76a93d-8d1c-405e-9f25-6e8d5a781098
0a5078
+    :setup: Replication setup with four suppliers
0a5078
+    :steps:
0a5078
+        1. Stop supplier 3
0a5078
+        2. Add a bunch of updates to supplier 4
0a5078
+        3. Disable replication on supplier 4
0a5078
+        4. Start supplier 3
0a5078
+        5. Remove agreements to supplier 4 from other suppliers
0a5078
+        6. Run a cleanallruv task on supplier 1 with a 'force' option 'on'
0a5078
+        7. Run one more cleanallruv task on supplier 1 with a 'force' option 'off'
0a5078
+        8. Check that everything was cleaned
0a5078
+    :expectedresults:
0a5078
+        1. Supplier 3 should be stopped
0a5078
+        2. Operation should be successful
0a5078
+        3. Replication on supplier 4 should be disabled
0a5078
+        4. Supplier 3 should be started
0a5078
+        5. Agreements to supplier 4 should be removed
0a5078
+        6. Operation should be successful
0a5078
+        7. Operation should be successful
0a5078
+        8. Everything should be cleaned
0a5078
+    """
0a5078
+
0a5078
+    log.info('Running test_multiple_tasks_with_force...')
0a5078
+
0a5078
+    # Stop supplier 3, while we update supplier 4, so that 3 is behind the other suppliers
0a5078
+    topology_m4.ms["supplier3"].stop()
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
+
0a5078
+    # Add a bunch of updates to supplier 4
0a5078
+    m4_add_users = AddUsers(topology_m4.ms["supplier4"], 10)
0a5078
+    m4_add_users.start()
0a5078
+    m4_add_users.join()
0a5078
+
0a5078
+    # Disable supplier 4
0a5078
+    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
+    remove_some_supplier4_agmts("test_multiple_tasks_with_force", topology_m4)
0a5078
+
0a5078
+    # Start supplier 3, it should be out of sync with the other replicas...
0a5078
+    topology_m4.ms["supplier3"].start()
0a5078
+
0a5078
+    # Remove the agreement to replica 4
0a5078
+    replica = Replicas(topology_m4.ms["supplier3"]).get(DEFAULT_SUFFIX)
0a5078
+    replica.get_agreements().get("004").delete()
0a5078
+
0a5078
+    # Run the task, use "force" because supplier 3 is not in sync with the other replicas
0a5078
+    # in regards to the replica 4 RUV
0a5078
+    log.info('test_multiple_tasks_with_force: run the cleanAllRUV task with "force" on...')
0a5078
+    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
+    cruv_task.create(properties={
0a5078
+        'replica-id': m4rid,
0a5078
+        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+        'replica-force-cleaning': 'yes',
0a5078
+        'replica-certify-all': 'no'
0a5078
+        })
0a5078
+
0a5078
+    log.info('test_multiple_tasks_with_force: run the cleanAllRUV task with "force" off...')
0a5078
+
0a5078
+    # NOTE: This must be try not py.test raises, because the above may or may
0a5078
+    # not have completed yet ....
0a5078
+    try:
0a5078
+        cruv_task_fail = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
+        cruv_task_fail.create(properties={
0a5078
+            'replica-id': m4rid,
0a5078
+            'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+            'replica-force-cleaning': 'no',
0a5078
+            'replica-certify-all': 'no'
0a5078
+            })
0a5078
+        cruv_task_fail.wait()
0a5078
+    except ldap.UNWILLING_TO_PERFORM:
0a5078
+        pass
0a5078
+    # Wait for the force task ....
0a5078
+    cruv_task.wait()
0a5078
+
0a5078
+    # Check the other supplier's RUV for 'replica 4'
0a5078
+    log.info('test_multiple_tasks_with_force: check all the suppliers have been cleaned...')
0a5078
+    clean = check_ruvs("test_clean_force", topology_m4, m4rid)
0a5078
+    assert clean
0a5078
+    # Check supplier 1 does not have the clean task running
0a5078
+    log.info('test_abort: check supplier 1 no longer has a cleanAllRUV task...')
0a5078
+    if not task_done(topology_m4, cruv_task.dn):
0a5078
+        log.fatal('test_abort: CleanAllRUV task was not aborted')
0a5078
+        assert False
0a5078
+
0a5078
+
0a5078
+if __name__ == '__main__':
0a5078
+    # Run isolated
0a5078
+    # -s for DEBUG mode
0a5078
+    CURRENT_FILE = os.path.realpath(__file__)
0a5078
+    pytest.main(["-s", CURRENT_FILE])
0a5078
+
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_restart_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_restart_test.py
0a5078
new file mode 100644
0a5078
index 000000000..2e8d7e4a6
0a5078
--- /dev/null
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_restart_test.py
0a5078
@@ -0,0 +1,161 @@
0a5078
+# --- BEGIN COPYRIGHT BLOCK ---
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
+# All rights reserved.
0a5078
+#
0a5078
+# License: GPL (version 3 or any later version).
0a5078
+# See LICENSE for details.
0a5078
+# --- END COPYRIGHT BLOCK ---
0a5078
+#
0a5078
+import logging
0a5078
+import pytest
0a5078
+import os
0a5078
+import time
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
+from lib389.topologies import topology_m4
0a5078
+from lib389.tasks import CleanAllRUVTask
0a5078
+from lib389.replica import ReplicationManager, Replicas
0a5078
+
0a5078
+log = logging.getLogger(__name__)
0a5078
+
0a5078
+
0a5078
+def remove_supplier4_agmts(msg, topology_m4):
0a5078
+    """Remove all the repl agmts to supplier4. """
0a5078
+
0a5078
+    log.info('%s: remove all the agreements to supplier 4...' % msg)
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    # This will delete m4 from the topo *and* remove all incoming agreements
0a5078
+    # to m4.
0a5078
+    repl.remove_supplier(topology_m4.ms["supplier4"],
0a5078
+        [topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]])
0a5078
+
0a5078
+def task_done(topology_m4, task_dn, timeout=60):
0a5078
+    """Check if the task is complete"""
0a5078
+
0a5078
+    attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode',
0a5078
+                'nsTaskCurrentItem', 'nsTaskTotalItems']
0a5078
+    done = False
0a5078
+    count = 0
0a5078
+
0a5078
+    while not done and count < timeout:
0a5078
+        try:
0a5078
+            entry = topology_m4.ms["supplier1"].getEntry(task_dn, attrlist=attrlist)
0a5078
+            if entry is not None:
0a5078
+                if entry.hasAttr('nsTaskExitCode'):
0a5078
+                    done = True
0a5078
+                    break
0a5078
+            else:
0a5078
+                done = True
0a5078
+                break
0a5078
+        except ldap.NO_SUCH_OBJECT:
0a5078
+            done = True
0a5078
+            break
0a5078
+        except ldap.LDAPError:
0a5078
+            break
0a5078
+        time.sleep(1)
0a5078
+        count += 1
0a5078
+
0a5078
+    return done
0a5078
+
0a5078
+
0a5078
+def check_ruvs(msg, topology_m4, m4rid):
0a5078
+    """Check suppliers 1-3 for supplier 4's rid."""
0a5078
+    for inst in (topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]):
0a5078
+        clean = False
0a5078
+        replicas = Replicas(inst)
0a5078
+        replica = replicas.get(DEFAULT_SUFFIX)
0a5078
+        log.info('check_ruvs for replica %s:%s (suffix:rid)' % (replica.get_suffix(), replica.get_rid()))
0a5078
+
0a5078
+        count = 0
0a5078
+        while not clean and count < 20:
0a5078
+            ruv = replica.get_ruv()
0a5078
+            if m4rid in ruv._rids:
0a5078
+                time.sleep(5)
0a5078
+                count = count + 1
0a5078
+            else:
0a5078
+                clean = True
0a5078
+        if not clean:
0a5078
+            raise Exception("Supplier %s was not cleaned in time." % inst.serverid)
0a5078
+    return True
0a5078
+    
0a5078
+
0a5078
+@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
+def test_clean_restart(topology_m4):
0a5078
+    """Check that cleanallruv task works properly after a restart
0a5078
+
0a5078
+    :id: c6233bb3-092c-4919-9ac9-80dd02cc6e02
0a5078
+    :setup: Replication setup with four suppliers
0a5078
+    :steps:
0a5078
+        1. Disable replication on supplier 4
0a5078
+        2. Remove agreements to supplier 4 from other suppliers
0a5078
+        3. Stop supplier 3
0a5078
+        4. Run a cleanallruv task on supplier 1
0a5078
+        5. Stop supplier 1
0a5078
+        6. Start supplier 3
0a5078
+        7. Make sure that no crash happened
0a5078
+        8. Start supplier 1
0a5078
+        9. Make sure that no crash happened
0a5078
+        10. Check that everything was cleaned
0a5078
+    :expectedresults:
0a5078
+        1. Operation should be successful
0a5078
+        2. Agreements to supplier 4 should be removed
0a5078
+        3. Supplier 3 should be stopped
0a5078
+        4. Cleanallruv task should be successfully executed
0a5078
+        5. Supplier 1 should be stopped
0a5078
+        6. Supplier 3 should be started
0a5078
+        7. No crash should happened
0a5078
+        8. Supplier 1 should be started
0a5078
+        9. No crash should happened
0a5078
+        10. Everything should be cleaned
0a5078
+    """
0a5078
+    log.info('Running test_clean_restart...')
0a5078
+
0a5078
+    # Disable supplier 4
0a5078
+    log.info('test_clean: disable supplier 4...')
0a5078
+
0a5078
+    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
+    remove_supplier4_agmts("test_clean", topology_m4)
0a5078
+
0a5078
+    # Stop supplier 3 to keep the task running, so we can stop supplier 1...
0a5078
+    topology_m4.ms["supplier3"].stop()
0a5078
+
0a5078
+    # Run the task
0a5078
+    log.info('test_clean: run the cleanAllRUV task...')
0a5078
+    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
+    cruv_task.create(properties={
0a5078
+        'replica-id': m4rid,
0a5078
+        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+        'replica-force-cleaning': 'no',
0a5078
+        'replica-certify-all': 'yes'
0a5078
+        })
0a5078
+
0a5078
+    # Sleep a bit, then stop supplier 1
0a5078
+    time.sleep(5)
0a5078
+    topology_m4.ms["supplier1"].stop()
0a5078
+
0a5078
+    # Now start supplier 3 & 1, and make sure we didn't crash
0a5078
+    topology_m4.ms["supplier3"].start()
0a5078
+    if topology_m4.ms["supplier3"].detectDisorderlyShutdown():
0a5078
+        log.fatal('test_clean_restart: Supplier 3 previously crashed!')
0a5078
+        assert False
0a5078
+
0a5078
+    topology_m4.ms["supplier1"].start(timeout=30)
0a5078
+    if topology_m4.ms["supplier1"].detectDisorderlyShutdown():
0a5078
+        log.fatal('test_clean_restart: Supplier 1 previously crashed!')
0a5078
+        assert False
0a5078
+
0a5078
+    # Check the other supplier's RUV for 'replica 4'
0a5078
+    log.info('test_clean_restart: check all the suppliers have been cleaned...')
0a5078
+    clean = check_ruvs("test_clean_restart", topology_m4, m4rid)
0a5078
+    assert clean
0a5078
+
0a5078
+    log.info('test_clean_restart PASSED, restoring supplier 4...')
0a5078
+
0a5078
+
0a5078
+if __name__ == '__main__':
0a5078
+    # Run isolated
0a5078
+    # -s for DEBUG mode
0a5078
+    CURRENT_FILE = os.path.realpath(__file__)
0a5078
+    pytest.main(["-s", CURRENT_FILE])
0a5078
+
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_shutdown_crash_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_shutdown_crash_test.py
0a5078
new file mode 100644
0a5078
index 000000000..b4b74e339
0a5078
--- /dev/null
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_shutdown_crash_test.py
0a5078
@@ -0,0 +1,123 @@
0a5078
+# --- BEGIN COPYRIGHT BLOCK ---
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
+# All rights reserved.
0a5078
+#
0a5078
+# License: GPL (version 3 or any later version).
0a5078
+# See LICENSE for details.
0a5078
+# --- END COPYRIGHT BLOCK ---
0a5078
+#
0a5078
+import logging
0a5078
+import pytest
0a5078
+import os
0a5078
+import time
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
+from lib389.topologies import topology_m4
0a5078
+from lib389.tasks import CleanAllRUVTask
0a5078
+from lib389.replica import ReplicationManager, Replicas
0a5078
+from lib389.config import CertmapLegacy
0a5078
+from lib389.idm.services import ServiceAccounts
0a5078
+
0a5078
+log = logging.getLogger(__name__)
0a5078
+
0a5078
+
0a5078
+def test_clean_shutdown_crash(topology_m2):
0a5078
+    """Check that server didn't crash after shutdown when running CleanAllRUV task
0a5078
+
0a5078
+    :id: c34d0b40-3c3e-4f53-8656-5e4c2a310aaf
0a5078
+    :setup: Replication setup with two suppliers
0a5078
+    :steps:
0a5078
+        1. Enable TLS on both suppliers
0a5078
+        2. Reconfigure both agreements to use TLS Client auth
0a5078
+        3. Stop supplier2
0a5078
+        4. Run the CleanAllRUV task
0a5078
+        5. Restart supplier1
0a5078
+        6. Check if supplier1 didn't crash
0a5078
+        7. Restart supplier1 again
0a5078
+        8. Check if supplier1 didn't crash
0a5078
+
0a5078
+    :expectedresults:
0a5078
+        1. Success
0a5078
+        2. Success
0a5078
+        3. Success
0a5078
+        4. Success
0a5078
+        5. Success
0a5078
+        6. Success
0a5078
+        7. Success
0a5078
+        8. Success
0a5078
+    """
0a5078
+
0a5078
+    m1 = topology_m2.ms["supplier1"]
0a5078
+    m2 = topology_m2.ms["supplier2"]
0a5078
+
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+
0a5078
+    cm_m1 = CertmapLegacy(m1)
0a5078
+    cm_m2 = CertmapLegacy(m2)
0a5078
+
0a5078
+    certmaps = cm_m1.list()
0a5078
+    certmaps['default']['DNComps'] = None
0a5078
+    certmaps['default']['CmapLdapAttr'] = 'nsCertSubjectDN'
0a5078
+
0a5078
+    cm_m1.set(certmaps)
0a5078
+    cm_m2.set(certmaps)
0a5078
+
0a5078
+    log.info('Enabling TLS')
0a5078
+    [i.enable_tls() for i in topology_m2]
0a5078
+
0a5078
+    log.info('Creating replication dns')
0a5078
+    services = ServiceAccounts(m1, DEFAULT_SUFFIX)
0a5078
+    repl_m1 = services.get('%s:%s' % (m1.host, m1.sslport))
0a5078
+    repl_m1.set('nsCertSubjectDN', m1.get_server_tls_subject())
0a5078
+
0a5078
+    repl_m2 = services.get('%s:%s' % (m2.host, m2.sslport))
0a5078
+    repl_m2.set('nsCertSubjectDN', m2.get_server_tls_subject())
0a5078
+
0a5078
+    log.info('Changing auth type')
0a5078
+    replica_m1 = Replicas(m1).get(DEFAULT_SUFFIX)
0a5078
+    agmt_m1 = replica_m1.get_agreements().list()[0]
0a5078
+    agmt_m1.replace_many(
0a5078
+        ('nsDS5ReplicaBindMethod', 'SSLCLIENTAUTH'),
0a5078
+        ('nsDS5ReplicaTransportInfo', 'SSL'),
0a5078
+        ('nsDS5ReplicaPort', '%s' % m2.sslport),
0a5078
+    )
0a5078
+
0a5078
+    agmt_m1.remove_all('nsDS5ReplicaBindDN')
0a5078
+
0a5078
+    replica_m2 = Replicas(m2).get(DEFAULT_SUFFIX)
0a5078
+    agmt_m2 = replica_m2.get_agreements().list()[0]
0a5078
+
0a5078
+    agmt_m2.replace_many(
0a5078
+        ('nsDS5ReplicaBindMethod', 'SSLCLIENTAUTH'),
0a5078
+        ('nsDS5ReplicaTransportInfo', 'SSL'),
0a5078
+        ('nsDS5ReplicaPort', '%s' % m1.sslport),
0a5078
+    )
0a5078
+    agmt_m2.remove_all('nsDS5ReplicaBindDN')
0a5078
+
0a5078
+    log.info('Stopping supplier2')
0a5078
+    m2.stop()
0a5078
+
0a5078
+    log.info('Run the cleanAllRUV task')
0a5078
+    cruv_task = CleanAllRUVTask(m1)
0a5078
+    cruv_task.create(properties={
0a5078
+        'replica-id': repl.get_rid(m1),
0a5078
+        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+        'replica-force-cleaning': 'no',
0a5078
+        'replica-certify-all': 'yes'
0a5078
+    })
0a5078
+
0a5078
+    m1.restart()
0a5078
+
0a5078
+    log.info('Check if supplier1 crashed')
0a5078
+    assert not m1.detectDisorderlyShutdown()
0a5078
+
0a5078
+    log.info('Repeat')
0a5078
+    m1.restart()
0a5078
+    assert not m1.detectDisorderlyShutdown()
0a5078
+
0a5078
+
0a5078
+if __name__ == '__main__':
0a5078
+    # Run isolated
0a5078
+    # -s for DEBUG mode
0a5078
+    CURRENT_FILE = os.path.realpath(__file__)
0a5078
+    pytest.main(["-s", CURRENT_FILE])
0a5078
+
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_stress_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_stress_test.py
0a5078
new file mode 100644
0a5078
index 000000000..0d43dd7d4
0a5078
--- /dev/null
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_stress_test.py
0a5078
@@ -0,0 +1,216 @@
0a5078
+# --- BEGIN COPYRIGHT BLOCK ---
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
+# All rights reserved.
0a5078
+#
0a5078
+# License: GPL (version 3 or any later version).
0a5078
+# See LICENSE for details.
0a5078
+# --- END COPYRIGHT BLOCK ---
0a5078
+#
0a5078
+import ldap
0a5078
+import logging
0a5078
+import pytest
0a5078
+import os
0a5078
+import random
0a5078
+import time
0a5078
+import threading
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
+from lib389.topologies import topology_m4
0a5078
+from lib389.tasks import CleanAllRUVTask
0a5078
+from lib389.idm.directorymanager import DirectoryManager
0a5078
+from lib389.idm.user import UserAccounts
0a5078
+from lib389.replica import ReplicationManager, Replicas
0a5078
+from lib389.config import LDBMConfig
0a5078
+
0a5078
+log = logging.getLogger(__name__)
0a5078
+
0a5078
+
0a5078
+class AddUsers(threading.Thread):
0a5078
+    def __init__(self, inst, num_users):
0a5078
+        threading.Thread.__init__(self)
0a5078
+        self.daemon = True
0a5078
+        self.inst = inst
0a5078
+        self.num_users = num_users
0a5078
+
0a5078
+    def run(self):
0a5078
+        """Start adding users"""
0a5078
+
0a5078
+        dm = DirectoryManager(self.inst)
0a5078
+        conn = dm.bind()
0a5078
+
0a5078
+        users = UserAccounts(conn, DEFAULT_SUFFIX)
0a5078
+
0a5078
+        u_range = list(range(self.num_users))
0a5078
+        random.shuffle(u_range)
0a5078
+
0a5078
+        for idx in u_range:
0a5078
+            try:
0a5078
+                users.create(properties={
0a5078
+                    'uid': 'testuser%s' % idx,
0a5078
+                    'cn' : 'testuser%s' % idx,
0a5078
+                    'sn' : 'user%s' % idx,
0a5078
+                    'uidNumber' : '%s' % (1000 + idx),
0a5078
+                    'gidNumber' : '%s' % (1000 + idx),
0a5078
+                    'homeDirectory' : '/home/testuser%s' % idx
0a5078
+                })
0a5078
+            # One of the suppliers was probably put into read only mode - just break out
0a5078
+            except ldap.UNWILLING_TO_PERFORM:
0a5078
+                break
0a5078
+            except ldap.ALREADY_EXISTS:
0a5078
+                pass
0a5078
+        conn.close()
0a5078
+
0a5078
+def remove_supplier4_agmts(msg, topology_m4):
0a5078
+    """Remove all the repl agmts to supplier4. """
0a5078
+
0a5078
+    log.info('%s: remove all the agreements to supplier 4...' % msg)
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    # This will delete m4 from the topo *and* remove all incoming agreements
0a5078
+    # to m4.
0a5078
+    repl.remove_supplier(topology_m4.ms["supplier4"],
0a5078
+        [topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]])
0a5078
+
0a5078
+def task_done(topology_m4, task_dn, timeout=60):
0a5078
+    """Check if the task is complete"""
0a5078
+
0a5078
+    attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode',
0a5078
+                'nsTaskCurrentItem', 'nsTaskTotalItems']
0a5078
+    done = False
0a5078
+    count = 0
0a5078
+
0a5078
+    while not done and count < timeout:
0a5078
+        try:
0a5078
+            entry = topology_m4.ms["supplier1"].getEntry(task_dn, attrlist=attrlist)
0a5078
+            if entry is not None:
0a5078
+                if entry.hasAttr('nsTaskExitCode'):
0a5078
+                    done = True
0a5078
+                    break
0a5078
+            else:
0a5078
+                done = True
0a5078
+                break
0a5078
+        except ldap.NO_SUCH_OBJECT:
0a5078
+            done = True
0a5078
+            break
0a5078
+        except ldap.LDAPError:
0a5078
+            break
0a5078
+        time.sleep(1)
0a5078
+        count += 1
0a5078
+
0a5078
+    return done
0a5078
+
0a5078
+def check_ruvs(msg, topology_m4, m4rid):
0a5078
+    """Check suppliers 1-3 for supplier 4's rid."""
0a5078
+    for inst in (topology_m4.ms["supplier1"], topology_m4.ms["supplier2"], topology_m4.ms["supplier3"]):
0a5078
+        clean = False
0a5078
+        replicas = Replicas(inst)
0a5078
+        replica = replicas.get(DEFAULT_SUFFIX)
0a5078
+        log.info('check_ruvs for replica %s:%s (suffix:rid)' % (replica.get_suffix(), replica.get_rid()))
0a5078
+
0a5078
+        count = 0
0a5078
+        while not clean and count < 20:
0a5078
+            ruv = replica.get_ruv()
0a5078
+            if m4rid in ruv._rids:
0a5078
+                time.sleep(5)
0a5078
+                count = count + 1
0a5078
+            else:
0a5078
+                clean = True
0a5078
+        if not clean:
0a5078
+            raise Exception("Supplier %s was not cleaned in time." % inst.serverid)
0a5078
+    return True
0a5078
+
0a5078
+
0a5078
+@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
+def test_stress_clean(topology_m4):
0a5078
+    """Put each server(m1 - m4) under a stress, and perform the entire clean process
0a5078
+
0a5078
+    :id: a8263cd6-f068-4357-86e0-e7c34504c8c5
0a5078
+    :setup: Replication setup with four suppliers
0a5078
+    :steps:
0a5078
+        1. Add a bunch of updates to all suppliers
0a5078
+        2. Put supplier 4 to read-only mode
0a5078
+        3. Disable replication on supplier 4
0a5078
+        4. Remove agreements to supplier 4 from other suppliers
0a5078
+        5. Run a cleanallruv task on supplier 1
0a5078
+        6. Check that everything was cleaned
0a5078
+    :expectedresults:
0a5078
+        1. Operation should be successful
0a5078
+        2. Supplier 4 should be put to read-only mode
0a5078
+        3. Replication on supplier 4 should be disabled
0a5078
+        4. Agreements to supplier 4 should be removed
0a5078
+        5. Operation should be successful
0a5078
+        6. Everything should be cleaned
0a5078
+    """
0a5078
+
0a5078
+    log.info('Running test_stress_clean...')
0a5078
+    log.info('test_stress_clean: put all the suppliers under load...')
0a5078
+
0a5078
+    ldbm_config = LDBMConfig(topology_m4.ms["supplier4"])
0a5078
+
0a5078
+    # Put all the suppliers under load
0a5078
+    # not too high load else it takes a long time to converge and
0a5078
+    # the test result becomes instable
0a5078
+    m1_add_users = AddUsers(topology_m4.ms["supplier1"], 200)
0a5078
+    m1_add_users.start()
0a5078
+    m2_add_users = AddUsers(topology_m4.ms["supplier2"], 200)
0a5078
+    m2_add_users.start()
0a5078
+    m3_add_users = AddUsers(topology_m4.ms["supplier3"], 200)
0a5078
+    m3_add_users.start()
0a5078
+    m4_add_users = AddUsers(topology_m4.ms["supplier4"], 200)
0a5078
+    m4_add_users.start()
0a5078
+
0a5078
+    # Allow sometime to get replication flowing in all directions
0a5078
+    log.info('test_stress_clean: allow some time for replication to get flowing...')
0a5078
+    time.sleep(5)
0a5078
+
0a5078
+    # Put supplier 4 into read only mode
0a5078
+    ldbm_config.set('nsslapd-readonly', 'on')
0a5078
+    # We need to wait for supplier 4 to push its changes out
0a5078
+    log.info('test_stress_clean: allow some time for supplier 4 to push changes out (60 seconds)...')
0a5078
+    time.sleep(60)
0a5078
+
0a5078
+    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
+    remove_supplier4_agmts("test_stress_clean", topology_m4)
0a5078
+
0a5078
+    # Run the task
0a5078
+    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
+    cruv_task.create(properties={
0a5078
+        'replica-id': m4rid,
0a5078
+        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
+        'replica-force-cleaning': 'no'
0a5078
+        })
0a5078
+    cruv_task.wait()
0a5078
+
0a5078
+    # Wait for the update to finish
0a5078
+    log.info('test_stress_clean: wait for all the updates to finish...')
0a5078
+    m1_add_users.join()
0a5078
+    m2_add_users.join()
0a5078
+    m3_add_users.join()
0a5078
+    m4_add_users.join()
0a5078
+
0a5078
+    # Check the other supplier's RUV for 'replica 4'
0a5078
+    log.info('test_stress_clean: check if all the replicas have been cleaned...')
0a5078
+    clean = check_ruvs("test_stress_clean", topology_m4, m4rid)
0a5078
+    assert clean
0a5078
+
0a5078
+    log.info('test_stress_clean:  PASSED, restoring supplier 4...')
0a5078
+
0a5078
+    # Sleep for a bit to replication complete
0a5078
+    log.info("Sleep for 120 seconds to allow replication to complete...")
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    repl.test_replication_topology([
0a5078
+        topology_m4.ms["supplier1"],
0a5078
+        topology_m4.ms["supplier2"],
0a5078
+        topology_m4.ms["supplier3"],
0a5078
+        ], timeout=120)
0a5078
+
0a5078
+    # Turn off readonly mode
0a5078
+    ldbm_config.set('nsslapd-readonly', 'off')
0a5078
+
0a5078
+
0a5078
+if __name__ == '__main__':
0a5078
+    # Run isolated
0a5078
+    # -s for DEBUG mode
0a5078
+    CURRENT_FILE = os.path.realpath(__file__)
0a5078
+    pytest.main(["-s", CURRENT_FILE])
0a5078
+
0a5078
diff --git a/dirsrvtests/tests/suites/replication/cleanallruv_test.py b/dirsrvtests/tests/suites/replication/cleanallruv_test.py
0a5078
index 1e9cd7c28..6d7141ada 100644
0a5078
--- a/dirsrvtests/tests/suites/replication/cleanallruv_test.py
0a5078
+++ b/dirsrvtests/tests/suites/replication/cleanallruv_test.py
0a5078
@@ -1,27 +1,20 @@
0a5078
 # --- BEGIN COPYRIGHT BLOCK ---
0a5078
-# Copyright (C) 2019 Red Hat, Inc.
0a5078
+# Copyright (C) 2022 Red Hat, Inc.
0a5078
 # All rights reserved.
0a5078
 #
0a5078
 # License: GPL (version 3 or any later version).
0a5078
 # See LICENSE for details.
0a5078
 # --- END COPYRIGHT BLOCK ---
0a5078
 #
0a5078
-import threading
0a5078
 import pytest
0a5078
-import random
0a5078
 from lib389 import DirSrv
0a5078
 from lib389.tasks import *
0a5078
 from lib389.utils import *
0a5078
 from lib389.topologies import topology_m4, topology_m2
0a5078
-from lib389._constants import *
0a5078
-
0a5078
-from lib389.idm.directorymanager import DirectoryManager
0a5078
+from lib389._constants import DEFAULT_SUFFIX
0a5078
 from lib389.replica import ReplicationManager, Replicas
0a5078
 from lib389.tasks import CleanAllRUVTask
0a5078
-from lib389.idm.user import UserAccounts
0a5078
-from lib389.config import LDBMConfig
0a5078
-from lib389.config import CertmapLegacy
0a5078
-from lib389.idm.services import ServiceAccounts
0a5078
+
0a5078
 
0a5078
 pytestmark = pytest.mark.tier1
0a5078
 
0a5078
@@ -29,42 +22,6 @@ logging.getLogger(__name__).setLevel(logging.DEBUG)
0a5078
 log = logging.getLogger(__name__)
0a5078
 
0a5078
 
0a5078
-class AddUsers(threading.Thread):
0a5078
-    def __init__(self, inst, num_users):
0a5078
-        threading.Thread.__init__(self)
0a5078
-        self.daemon = True
0a5078
-        self.inst = inst
0a5078
-        self.num_users = num_users
0a5078
-
0a5078
-    def run(self):
0a5078
-        """Start adding users"""
0a5078
-
0a5078
-        dm = DirectoryManager(self.inst)
0a5078
-        conn = dm.bind()
0a5078
-
0a5078
-        users = UserAccounts(conn, DEFAULT_SUFFIX)
0a5078
-
0a5078
-        u_range = list(range(self.num_users))
0a5078
-        random.shuffle(u_range)
0a5078
-
0a5078
-        for idx in u_range:
0a5078
-            try:
0a5078
-                users.create(properties={
0a5078
-                    'uid': 'testuser%s' % idx,
0a5078
-                    'cn' : 'testuser%s' % idx,
0a5078
-                    'sn' : 'user%s' % idx,
0a5078
-                    'uidNumber' : '%s' % (1000 + idx),
0a5078
-                    'gidNumber' : '%s' % (1000 + idx),
0a5078
-                    'homeDirectory' : '/home/testuser%s' % idx
0a5078
-                })
0a5078
-            # One of the suppliers was probably put into read only mode - just break out
0a5078
-            except ldap.UNWILLING_TO_PERFORM:
0a5078
-                break
0a5078
-            except ldap.ALREADY_EXISTS:
0a5078
-                pass
0a5078
-        conn.close()
0a5078
-
0a5078
-
0a5078
 def remove_supplier4_agmts(msg, topology_m4):
0a5078
     """Remove all the repl agmts to supplier4. """
0a5078
 
0a5078
@@ -96,92 +53,7 @@ def check_ruvs(msg, topology_m4, m4rid):
0a5078
     return True
0a5078
 
0a5078
 
0a5078
-def task_done(topology_m4, task_dn, timeout=60):
0a5078
-    """Check if the task is complete"""
0a5078
-
0a5078
-    attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode',
0a5078
-                'nsTaskCurrentItem', 'nsTaskTotalItems']
0a5078
-    done = False
0a5078
-    count = 0
0a5078
-
0a5078
-    while not done and count < timeout:
0a5078
-        try:
0a5078
-            entry = topology_m4.ms["supplier1"].getEntry(task_dn, attrlist=attrlist)
0a5078
-            if entry is not None:
0a5078
-                if entry.hasAttr('nsTaskExitCode'):
0a5078
-                    done = True
0a5078
-                    break
0a5078
-            else:
0a5078
-                done = True
0a5078
-                break
0a5078
-        except ldap.NO_SUCH_OBJECT:
0a5078
-            done = True
0a5078
-            break
0a5078
-        except ldap.LDAPError:
0a5078
-            break
0a5078
-        time.sleep(1)
0a5078
-        count += 1
0a5078
-
0a5078
-    return done
0a5078
-
0a5078
-
0a5078
-def restore_supplier4(topology_m4):
0a5078
-    """In our tests will always be removing supplier 4, so we need a common
0a5078
-    way to restore it for another test
0a5078
-    """
0a5078
-
0a5078
-    # Restart the remaining suppliers to allow rid 4 to be reused.
0a5078
-    for inst in topology_m4.ms.values():
0a5078
-        inst.restart()
0a5078
-
0a5078
-    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
-    repl.join_supplier(topology_m4.ms["supplier1"], topology_m4.ms["supplier4"])
0a5078
-
0a5078
-    # Add the 2,3 -> 4 agmt.
0a5078
-    repl.ensure_agreement(topology_m4.ms["supplier2"], topology_m4.ms["supplier4"])
0a5078
-    repl.ensure_agreement(topology_m4.ms["supplier3"], topology_m4.ms["supplier4"])
0a5078
-    # And in reverse ...
0a5078
-    repl.ensure_agreement(topology_m4.ms["supplier4"], topology_m4.ms["supplier2"])
0a5078
-    repl.ensure_agreement(topology_m4.ms["supplier4"], topology_m4.ms["supplier3"])
0a5078
-
0a5078
-    log.info('Supplier 4 has been successfully restored.')
0a5078
-
0a5078
-
0a5078
-@pytest.fixture()
0a5078
-def m4rid(request, topology_m4):
0a5078
-    log.debug("Wait a bit before the reset - it is required for the slow machines")
0a5078
-    time.sleep(5)
0a5078
-    log.debug("-------------- BEGIN RESET of m4 -----------------")
0a5078
-    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
-    repl.test_replication_topology(topology_m4.ms.values())
0a5078
-    # What is supplier4's rid?
0a5078
-    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
-
0a5078
-    def fin():
0a5078
-        try:
0a5078
-            # Restart the suppliers and rerun cleanallruv
0a5078
-            for inst in topology_m4.ms.values():
0a5078
-                inst.restart()
0a5078
-
0a5078
-            cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-            cruv_task.create(properties={
0a5078
-                'replica-id': m4rid,
0a5078
-                'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-                'replica-force-cleaning': 'no',
0a5078
-                })
0a5078
-            cruv_task.wait()
0a5078
-        except ldap.UNWILLING_TO_PERFORM:
0a5078
-            # In some casse we already cleaned rid4, so if we fail, it's okay
0a5078
-            pass
0a5078
-        restore_supplier4(topology_m4)
0a5078
-        # Make sure everything works.
0a5078
-        repl.test_replication_topology(topology_m4.ms.values())
0a5078
-    request.addfinalizer(fin)
0a5078
-    log.debug("-------------- FINISH RESET of m4 -----------------")
0a5078
-    return m4rid
0a5078
-
0a5078
-
0a5078
-def test_clean(topology_m4, m4rid):
0a5078
+def test_clean(topology_m4):
0a5078
     """Check that cleanallruv task works properly
0a5078
 
0a5078
     :id: e9b3ce5c-e17c-409e-aafc-e97d630f2878
0a5078
@@ -204,6 +76,8 @@ def test_clean(topology_m4, m4rid):
0a5078
     # Disable supplier 4
0a5078
     # Remove the agreements from the other suppliers that point to supplier 4
0a5078
     log.info('test_clean: disable supplier 4...')
0a5078
+    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
+    m4rid = repl.get_rid(topology_m4.ms["supplier4"])
0a5078
     remove_supplier4_agmts("test_clean", topology_m4)
0a5078
 
0a5078
     # Run the task
0a5078
@@ -221,610 +95,6 @@ def test_clean(topology_m4, m4rid):
0a5078
     clean = check_ruvs("test_clean", topology_m4, m4rid)
0a5078
     assert clean
0a5078
 
0a5078
-    log.info('test_clean PASSED, restoring supplier 4...')
0a5078
-
0a5078
-@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
-def test_clean_restart(topology_m4, m4rid):
0a5078
-    """Check that cleanallruv task works properly after a restart
0a5078
-
0a5078
-    :id: c6233bb3-092c-4919-9ac9-80dd02cc6e02
0a5078
-    :setup: Replication setup with four suppliers
0a5078
-    :steps:
0a5078
-        1. Disable replication on supplier 4
0a5078
-        2. Remove agreements to supplier 4 from other suppliers
0a5078
-        3. Stop supplier 3
0a5078
-        4. Run a cleanallruv task on supplier 1
0a5078
-        5. Stop supplier 1
0a5078
-        6. Start supplier 3
0a5078
-        7. Make sure that no crash happened
0a5078
-        8. Start supplier 1
0a5078
-        9. Make sure that no crash happened
0a5078
-        10. Check that everything was cleaned
0a5078
-    :expectedresults:
0a5078
-        1. Operation should be successful
0a5078
-        2. Agreements to supplier 4 should be removed
0a5078
-        3. Supplier 3 should be stopped
0a5078
-        4. Cleanallruv task should be successfully executed
0a5078
-        5. Supplier 1 should be stopped
0a5078
-        6. Supplier 3 should be started
0a5078
-        7. No crash should happened
0a5078
-        8. Supplier 1 should be started
0a5078
-        9. No crash should happened
0a5078
-        10. Everything should be cleaned
0a5078
-    """
0a5078
-    log.info('Running test_clean_restart...')
0a5078
-
0a5078
-    # Disable supplier 4
0a5078
-    log.info('test_clean: disable supplier 4...')
0a5078
-    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
-    remove_supplier4_agmts("test_clean", topology_m4)
0a5078
-
0a5078
-    # Stop supplier 3 to keep the task running, so we can stop supplier 1...
0a5078
-    topology_m4.ms["supplier3"].stop()
0a5078
-
0a5078
-    # Run the task
0a5078
-    log.info('test_clean: run the cleanAllRUV task...')
0a5078
-    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-    cruv_task.create(properties={
0a5078
-        'replica-id': m4rid,
0a5078
-        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-        'replica-force-cleaning': 'no',
0a5078
-        'replica-certify-all': 'yes'
0a5078
-        })
0a5078
-
0a5078
-    # Sleep a bit, then stop supplier 1
0a5078
-    time.sleep(5)
0a5078
-    topology_m4.ms["supplier1"].stop()
0a5078
-
0a5078
-    # Now start supplier 3 & 1, and make sure we didn't crash
0a5078
-    topology_m4.ms["supplier3"].start()
0a5078
-    if topology_m4.ms["supplier3"].detectDisorderlyShutdown():
0a5078
-        log.fatal('test_clean_restart: Supplier 3 previously crashed!')
0a5078
-        assert False
0a5078
-
0a5078
-    topology_m4.ms["supplier1"].start(timeout=30)
0a5078
-    if topology_m4.ms["supplier1"].detectDisorderlyShutdown():
0a5078
-        log.fatal('test_clean_restart: Supplier 1 previously crashed!')
0a5078
-        assert False
0a5078
-
0a5078
-    # Check the other supplier's RUV for 'replica 4'
0a5078
-    log.info('test_clean_restart: check all the suppliers have been cleaned...')
0a5078
-    clean = check_ruvs("test_clean_restart", topology_m4, m4rid)
0a5078
-    assert clean
0a5078
-
0a5078
-    log.info('test_clean_restart PASSED, restoring supplier 4...')
0a5078
-
0a5078
-
0a5078
-@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
-def test_clean_force(topology_m4, m4rid):
0a5078
-    """Check that multiple tasks with a 'force' option work properly
0a5078
-
0a5078
-    :id: f8810dfe-d2d2-4dd9-ba03-5fc14896fabe
0a5078
-    :setup: Replication setup with four suppliers
0a5078
-    :steps:
0a5078
-        1. Stop supplier 3
0a5078
-        2. Add a bunch of updates to supplier 4
0a5078
-        3. Disable replication on supplier 4
0a5078
-        4. Start supplier 3
0a5078
-        5. Remove agreements to supplier 4 from other suppliers
0a5078
-        6. Run a cleanallruv task on supplier 1 with a 'force' option 'on'
0a5078
-        7. Check that everything was cleaned
0a5078
-    :expectedresults:
0a5078
-        1. Supplier 3 should be stopped
0a5078
-        2. Operation should be successful
0a5078
-        3. Replication on supplier 4 should be disabled
0a5078
-        4. Supplier 3 should be started
0a5078
-        5. Agreements to supplier 4 should be removed
0a5078
-        6. Operation should be successful
0a5078
-        7. Everything should be cleaned
0a5078
-    """
0a5078
-
0a5078
-    log.info('Running test_clean_force...')
0a5078
-
0a5078
-    # Stop supplier 3, while we update supplier 4, so that 3 is behind the other suppliers
0a5078
-    topology_m4.ms["supplier3"].stop()
0a5078
-
0a5078
-    # Add a bunch of updates to supplier 4
0a5078
-    m4_add_users = AddUsers(topology_m4.ms["supplier4"], 1500)
0a5078
-    m4_add_users.start()
0a5078
-    m4_add_users.join()
0a5078
-
0a5078
-    # Start supplier 3, it should be out of sync with the other replicas...
0a5078
-    topology_m4.ms["supplier3"].start()
0a5078
-
0a5078
-    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
-    remove_supplier4_agmts("test_clean_force", topology_m4)
0a5078
-
0a5078
-    # Run the task, use "force" because supplier 3 is not in sync with the other replicas
0a5078
-    # in regards to the replica 4 RUV
0a5078
-    log.info('test_clean: run the cleanAllRUV task...')
0a5078
-    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-    cruv_task.create(properties={
0a5078
-        'replica-id': m4rid,
0a5078
-        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-        'replica-force-cleaning': 'yes'
0a5078
-        })
0a5078
-    cruv_task.wait()
0a5078
-
0a5078
-    # Check the other supplier's RUV for 'replica 4'
0a5078
-    log.info('test_clean_force: check all the suppliers have been cleaned...')
0a5078
-    clean = check_ruvs("test_clean_force", topology_m4, m4rid)
0a5078
-    assert clean
0a5078
-
0a5078
-    log.info('test_clean_force PASSED, restoring supplier 4...')
0a5078
-
0a5078
-
0a5078
-@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
-def test_abort(topology_m4, m4rid):
0a5078
-    """Test the abort task basic functionality
0a5078
-
0a5078
-    :id: b09a6887-8de0-4fac-8e41-73ccbaaf7a08
0a5078
-    :setup: Replication setup with four suppliers
0a5078
-    :steps:
0a5078
-        1. Disable replication on supplier 4
0a5078
-        2. Remove agreements to supplier 4 from other suppliers
0a5078
-        3. Stop supplier 2
0a5078
-        4. Run a cleanallruv task on supplier 1
0a5078
-        5. Run a cleanallruv abort task on supplier 1
0a5078
-    :expectedresults: No hanging tasks left
0a5078
-        1. Replication on supplier 4 should be disabled
0a5078
-        2. Agreements to supplier 4 should be removed
0a5078
-        3. Supplier 2 should be stopped
0a5078
-        4. Operation should be successful
0a5078
-        5. Operation should be successful
0a5078
-    """
0a5078
-
0a5078
-    log.info('Running test_abort...')
0a5078
-    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
-    remove_supplier4_agmts("test_abort", topology_m4)
0a5078
-
0a5078
-    # Stop supplier 2
0a5078
-    log.info('test_abort: stop supplier 2 to freeze the cleanAllRUV task...')
0a5078
-    topology_m4.ms["supplier2"].stop()
0a5078
-
0a5078
-    # Run the task
0a5078
-    log.info('test_abort: add the cleanAllRUV task...')
0a5078
-    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-    cruv_task.create(properties={
0a5078
-        'replica-id': m4rid,
0a5078
-        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-        'replica-force-cleaning': 'no',
0a5078
-        'replica-certify-all': 'yes'
0a5078
-        })
0a5078
-    # Wait a bit
0a5078
-    time.sleep(2)
0a5078
-
0a5078
-    # Abort the task
0a5078
-    cruv_task.abort()
0a5078
-
0a5078
-    # Check supplier 1 does not have the clean task running
0a5078
-    log.info('test_abort: check supplier 1 no longer has a cleanAllRUV task...')
0a5078
-    if not task_done(topology_m4, cruv_task.dn):
0a5078
-        log.fatal('test_abort: CleanAllRUV task was not aborted')
0a5078
-        assert False
0a5078
-
0a5078
-    # Start supplier 2
0a5078
-    log.info('test_abort: start supplier 2 to begin the restore process...')
0a5078
-    topology_m4.ms["supplier2"].start()
0a5078
-
0a5078
-    log.info('test_abort PASSED, restoring supplier 4...')
0a5078
-
0a5078
-
0a5078
-@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
-def test_abort_restart(topology_m4, m4rid):
0a5078
-    """Test the abort task can handle a restart, and then resume
0a5078
-
0a5078
-    :id: b66e33d4-fe85-4e1c-b882-75da80f70ab3
0a5078
-    :setup: Replication setup with four suppliers
0a5078
-    :steps:
0a5078
-        1. Disable replication on supplier 4
0a5078
-        2. Remove agreements to supplier 4 from other suppliers
0a5078
-        3. Stop supplier 3
0a5078
-        4. Run a cleanallruv task on supplier 1
0a5078
-        5. Run a cleanallruv abort task on supplier 1
0a5078
-        6. Restart supplier 1
0a5078
-        7. Make sure that no crash happened
0a5078
-        8. Start supplier 3
0a5078
-        9. Check supplier 1 does not have the clean task running
0a5078
-        10. Check that errors log doesn't have 'Aborting abort task' message
0a5078
-    :expectedresults:
0a5078
-        1. Replication on supplier 4 should be disabled
0a5078
-        2. Agreements to supplier 4 should be removed
0a5078
-        3. Supplier 3 should be stopped
0a5078
-        4. Operation should be successful
0a5078
-        5. Operation should be successful
0a5078
-        6. Supplier 1 should be restarted
0a5078
-        7. No crash should happened
0a5078
-        8. Supplier 3 should be started
0a5078
-        9. Check supplier 1 shouldn't have the clean task running
0a5078
-        10. Errors log shouldn't have 'Aborting abort task' message
0a5078
-    """
0a5078
-
0a5078
-    log.info('Running test_abort_restart...')
0a5078
-    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
-    remove_supplier4_agmts("test_abort", topology_m4)
0a5078
-
0a5078
-    # Stop supplier 3
0a5078
-    log.info('test_abort_restart: stop supplier 3 to freeze the cleanAllRUV task...')
0a5078
-    topology_m4.ms["supplier3"].stop()
0a5078
-
0a5078
-    # Run the task
0a5078
-    log.info('test_abort_restart: add the cleanAllRUV task...')
0a5078
-    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-    cruv_task.create(properties={
0a5078
-        'replica-id': m4rid,
0a5078
-        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-        'replica-force-cleaning': 'no',
0a5078
-        'replica-certify-all': 'yes'
0a5078
-        })
0a5078
-    # Wait a bit
0a5078
-    time.sleep(2)
0a5078
-
0a5078
-    # Abort the task
0a5078
-    cruv_task.abort(certify=True)
0a5078
-
0a5078
-    # Check supplier 1 does not have the clean task running
0a5078
-    log.info('test_abort_abort: check supplier 1 no longer has a cleanAllRUV task...')
0a5078
-    if not task_done(topology_m4, cruv_task.dn):
0a5078
-        log.fatal('test_abort_restart: CleanAllRUV task was not aborted')
0a5078
-        assert False
0a5078
-
0a5078
-    # Now restart supplier 1, and make sure the abort process completes
0a5078
-    topology_m4.ms["supplier1"].restart()
0a5078
-    if topology_m4.ms["supplier1"].detectDisorderlyShutdown():
0a5078
-        log.fatal('test_abort_restart: Supplier 1 previously crashed!')
0a5078
-        assert False
0a5078
-
0a5078
-    # Start supplier 3
0a5078
-    topology_m4.ms["supplier3"].start()
0a5078
-
0a5078
-    # Need to wait 5 seconds before server processes any leftover tasks
0a5078
-    time.sleep(6)
0a5078
-
0a5078
-    # Check supplier 1 tried to run abort task.  We expect the abort task to be aborted.
0a5078
-    if not topology_m4.ms["supplier1"].searchErrorsLog('Aborting abort task'):
0a5078
-        log.fatal('test_abort_restart: Abort task did not restart')
0a5078
-        assert False
0a5078
-
0a5078
-    log.info('test_abort_restart PASSED, restoring supplier 4...')
0a5078
-
0a5078
-
0a5078
-@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
-def test_abort_certify(topology_m4, m4rid):
0a5078
-    """Test the abort task with a replica-certify-all option
0a5078
-
0a5078
-    :id: 78959966-d644-44a8-b98c-1fcf21b45eb0
0a5078
-    :setup: Replication setup with four suppliers
0a5078
-    :steps:
0a5078
-        1. Disable replication on supplier 4
0a5078
-        2. Remove agreements to supplier 4 from other suppliers
0a5078
-        3. Stop supplier 2
0a5078
-        4. Run a cleanallruv task on supplier 1
0a5078
-        5. Run a cleanallruv abort task on supplier 1 with a replica-certify-all option
0a5078
-    :expectedresults: No hanging tasks left
0a5078
-        1. Replication on supplier 4 should be disabled
0a5078
-        2. Agreements to supplier 4 should be removed
0a5078
-        3. Supplier 2 should be stopped
0a5078
-        4. Operation should be successful
0a5078
-        5. Operation should be successful
0a5078
-    """
0a5078
-
0a5078
-    log.info('Running test_abort_certify...')
0a5078
-
0a5078
-    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
-    remove_supplier4_agmts("test_abort_certify", topology_m4)
0a5078
-
0a5078
-    # Stop supplier 2
0a5078
-    log.info('test_abort_certify: stop supplier 2 to freeze the cleanAllRUV task...')
0a5078
-    topology_m4.ms["supplier2"].stop()
0a5078
-
0a5078
-    # Run the task
0a5078
-    log.info('test_abort_certify: add the cleanAllRUV task...')
0a5078
-    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-    cruv_task.create(properties={
0a5078
-        'replica-id': m4rid,
0a5078
-        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-        'replica-force-cleaning': 'no',
0a5078
-        'replica-certify-all': 'yes'
0a5078
-        })
0a5078
-    # Wait a bit
0a5078
-    time.sleep(2)
0a5078
-
0a5078
-    # Abort the task
0a5078
-    log.info('test_abort_certify: abort the cleanAllRUV task...')
0a5078
-    abort_task = cruv_task.abort(certify=True)
0a5078
-
0a5078
-    # Wait a while and make sure the abort task is still running
0a5078
-    log.info('test_abort_certify...')
0a5078
-
0a5078
-    if task_done(topology_m4, abort_task.dn, 10):
0a5078
-        log.fatal('test_abort_certify: abort task incorrectly finished')
0a5078
-        assert False
0a5078
-
0a5078
-    # Now start supplier 2 so it can be aborted
0a5078
-    log.info('test_abort_certify: start supplier 2 to allow the abort task to finish...')
0a5078
-    topology_m4.ms["supplier2"].start()
0a5078
-
0a5078
-    # Wait for the abort task to stop
0a5078
-    if not task_done(topology_m4, abort_task.dn, 90):
0a5078
-        log.fatal('test_abort_certify: The abort CleanAllRUV task was not aborted')
0a5078
-        assert False
0a5078
-
0a5078
-    # Check supplier 1 does not have the clean task running
0a5078
-    log.info('test_abort_certify: check supplier 1 no longer has a cleanAllRUV task...')
0a5078
-    if not task_done(topology_m4, cruv_task.dn):
0a5078
-        log.fatal('test_abort_certify: CleanAllRUV task was not aborted')
0a5078
-        assert False
0a5078
-
0a5078
-    log.info('test_abort_certify PASSED, restoring supplier 4...')
0a5078
-
0a5078
-
0a5078
-@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
-def test_stress_clean(topology_m4, m4rid):
0a5078
-    """Put each server(m1 - m4) under a stress, and perform the entire clean process
0a5078
-
0a5078
-    :id: a8263cd6-f068-4357-86e0-e7c34504c8c5
0a5078
-    :setup: Replication setup with four suppliers
0a5078
-    :steps:
0a5078
-        1. Add a bunch of updates to all suppliers
0a5078
-        2. Put supplier 4 to read-only mode
0a5078
-        3. Disable replication on supplier 4
0a5078
-        4. Remove agreements to supplier 4 from other suppliers
0a5078
-        5. Run a cleanallruv task on supplier 1
0a5078
-        6. Check that everything was cleaned
0a5078
-    :expectedresults:
0a5078
-        1. Operation should be successful
0a5078
-        2. Supplier 4 should be put to read-only mode
0a5078
-        3. Replication on supplier 4 should be disabled
0a5078
-        4. Agreements to supplier 4 should be removed
0a5078
-        5. Operation should be successful
0a5078
-        6. Everything should be cleaned
0a5078
-    """
0a5078
-
0a5078
-    log.info('Running test_stress_clean...')
0a5078
-    log.info('test_stress_clean: put all the suppliers under load...')
0a5078
-
0a5078
-    ldbm_config = LDBMConfig(topology_m4.ms["supplier4"])
0a5078
-
0a5078
-    # not too high load else it takes a long time to converge and
0a5078
-    # the test result becomes instable
0a5078
-    m1_add_users = AddUsers(topology_m4.ms["supplier1"], 500)
0a5078
-    m1_add_users.start()
0a5078
-    m2_add_users = AddUsers(topology_m4.ms["supplier2"], 500)
0a5078
-    m2_add_users.start()
0a5078
-    m3_add_users = AddUsers(topology_m4.ms["supplier3"], 500)
0a5078
-    m3_add_users.start()
0a5078
-    m4_add_users = AddUsers(topology_m4.ms["supplier4"], 500)
0a5078
-    m4_add_users.start()
0a5078
-
0a5078
-    # Allow sometime to get replication flowing in all directions
0a5078
-    log.info('test_stress_clean: allow some time for replication to get flowing...')
0a5078
-    time.sleep(5)
0a5078
-
0a5078
-    # Put supplier 4 into read only mode
0a5078
-    ldbm_config.set('nsslapd-readonly', 'on')
0a5078
-    # We need to wait for supplier 4 to push its changes out
0a5078
-    log.info('test_stress_clean: allow some time for supplier 4 to push changes out (60 seconds)...')
0a5078
-    time.sleep(30)
0a5078
-
0a5078
-    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
-    remove_supplier4_agmts("test_stress_clean", topology_m4)
0a5078
-
0a5078
-    # Run the task
0a5078
-    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-    cruv_task.create(properties={
0a5078
-        'replica-id': m4rid,
0a5078
-        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-        'replica-force-cleaning': 'no'
0a5078
-        })
0a5078
-    cruv_task.wait()
0a5078
-
0a5078
-    # Wait for the update to finish
0a5078
-    log.info('test_stress_clean: wait for all the updates to finish...')
0a5078
-    m1_add_users.join()
0a5078
-    m2_add_users.join()
0a5078
-    m3_add_users.join()
0a5078
-    m4_add_users.join()
0a5078
-
0a5078
-    # Check the other supplier's RUV for 'replica 4'
0a5078
-    log.info('test_stress_clean: check if all the replicas have been cleaned...')
0a5078
-    clean = check_ruvs("test_stress_clean", topology_m4, m4rid)
0a5078
-    assert clean
0a5078
-
0a5078
-    log.info('test_stress_clean:  PASSED, restoring supplier 4...')
0a5078
-
0a5078
-    # Sleep for a bit to replication complete
0a5078
-    log.info("Sleep for 120 seconds to allow replication to complete...")
0a5078
-    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
-    repl.test_replication_topology([
0a5078
-        topology_m4.ms["supplier1"],
0a5078
-        topology_m4.ms["supplier2"],
0a5078
-        topology_m4.ms["supplier3"],
0a5078
-        ], timeout=120)
0a5078
-
0a5078
-    # Turn off readonly mode
0a5078
-    ldbm_config.set('nsslapd-readonly', 'off')
0a5078
-
0a5078
-
0a5078
-@pytest.mark.flaky(max_runs=2, min_passes=1)
0a5078
-def test_multiple_tasks_with_force(topology_m4, m4rid):
0a5078
-    """Check that multiple tasks with a 'force' option work properly
0a5078
-
0a5078
-    :id: eb76a93d-8d1c-405e-9f25-6e8d5a781098
0a5078
-    :setup: Replication setup with four suppliers
0a5078
-    :steps:
0a5078
-        1. Stop supplier 3
0a5078
-        2. Add a bunch of updates to supplier 4
0a5078
-        3. Disable replication on supplier 4
0a5078
-        4. Start supplier 3
0a5078
-        5. Remove agreements to supplier 4 from other suppliers
0a5078
-        6. Run a cleanallruv task on supplier 1 with a 'force' option 'on'
0a5078
-        7. Run one more cleanallruv task on supplier 1 with a 'force' option 'off'
0a5078
-        8. Check that everything was cleaned
0a5078
-    :expectedresults:
0a5078
-        1. Supplier 3 should be stopped
0a5078
-        2. Operation should be successful
0a5078
-        3. Replication on supplier 4 should be disabled
0a5078
-        4. Supplier 3 should be started
0a5078
-        5. Agreements to supplier 4 should be removed
0a5078
-        6. Operation should be successful
0a5078
-        7. Operation should be successful
0a5078
-        8. Everything should be cleaned
0a5078
-    """
0a5078
-
0a5078
-    log.info('Running test_multiple_tasks_with_force...')
0a5078
-
0a5078
-    # Stop supplier 3, while we update supplier 4, so that 3 is behind the other suppliers
0a5078
-    topology_m4.ms["supplier3"].stop()
0a5078
-
0a5078
-    # Add a bunch of updates to supplier 4
0a5078
-    m4_add_users = AddUsers(topology_m4.ms["supplier4"], 1500)
0a5078
-    m4_add_users.start()
0a5078
-    m4_add_users.join()
0a5078
-
0a5078
-    # Start supplier 3, it should be out of sync with the other replicas...
0a5078
-    topology_m4.ms["supplier3"].start()
0a5078
-
0a5078
-    # Disable supplier 4
0a5078
-    # Remove the agreements from the other suppliers that point to supplier 4
0a5078
-    remove_supplier4_agmts("test_multiple_tasks_with_force", topology_m4)
0a5078
-
0a5078
-    # Run the task, use "force" because supplier 3 is not in sync with the other replicas
0a5078
-    # in regards to the replica 4 RUV
0a5078
-    log.info('test_multiple_tasks_with_force: run the cleanAllRUV task with "force" on...')
0a5078
-    cruv_task = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-    cruv_task.create(properties={
0a5078
-        'replica-id': m4rid,
0a5078
-        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-        'replica-force-cleaning': 'yes',
0a5078
-        'replica-certify-all': 'no'
0a5078
-        })
0a5078
-
0a5078
-    log.info('test_multiple_tasks_with_force: run the cleanAllRUV task with "force" off...')
0a5078
-
0a5078
-    # NOTE: This must be try not py.test raises, because the above may or may
0a5078
-    # not have completed yet ....
0a5078
-    try:
0a5078
-        cruv_task_fail = CleanAllRUVTask(topology_m4.ms["supplier1"])
0a5078
-        cruv_task_fail.create(properties={
0a5078
-            'replica-id': m4rid,
0a5078
-            'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-            'replica-force-cleaning': 'no',
0a5078
-            'replica-certify-all': 'no'
0a5078
-            })
0a5078
-        cruv_task_fail.wait()
0a5078
-    except ldap.UNWILLING_TO_PERFORM:
0a5078
-        pass
0a5078
-    # Wait for the force task ....
0a5078
-    cruv_task.wait()
0a5078
-
0a5078
-    # Check the other supplier's RUV for 'replica 4'
0a5078
-    log.info('test_multiple_tasks_with_force: check all the suppliers have been cleaned...')
0a5078
-    clean = check_ruvs("test_clean_force", topology_m4, m4rid)
0a5078
-    assert clean
0a5078
-    # Check supplier 1 does not have the clean task running
0a5078
-    log.info('test_abort: check supplier 1 no longer has a cleanAllRUV task...')
0a5078
-    if not task_done(topology_m4, cruv_task.dn):
0a5078
-        log.fatal('test_abort: CleanAllRUV task was not aborted')
0a5078
-        assert False
0a5078
-
0a5078
-
0a5078
-@pytest.mark.bz1466441
0a5078
-@pytest.mark.ds50370
0a5078
-def test_clean_shutdown_crash(topology_m2):
0a5078
-    """Check that server didn't crash after shutdown when running CleanAllRUV task
0a5078
-
0a5078
-    :id: c34d0b40-3c3e-4f53-8656-5e4c2a310aaf
0a5078
-    :setup: Replication setup with two suppliers
0a5078
-    :steps:
0a5078
-        1. Enable TLS on both suppliers
0a5078
-        2. Reconfigure both agreements to use TLS Client auth
0a5078
-        3. Stop supplier2
0a5078
-        4. Run the CleanAllRUV task
0a5078
-        5. Restart supplier1
0a5078
-        6. Check if supplier1 didn't crash
0a5078
-        7. Restart supplier1 again
0a5078
-        8. Check if supplier1 didn't crash
0a5078
-
0a5078
-    :expectedresults:
0a5078
-        1. Success
0a5078
-        2. Success
0a5078
-        3. Success
0a5078
-        4. Success
0a5078
-        5. Success
0a5078
-        6. Success
0a5078
-        7. Success
0a5078
-        8. Success
0a5078
-    """
0a5078
-
0a5078
-    m1 = topology_m2.ms["supplier1"]
0a5078
-    m2 = topology_m2.ms["supplier2"]
0a5078
-
0a5078
-    repl = ReplicationManager(DEFAULT_SUFFIX)
0a5078
-
0a5078
-    cm_m1 = CertmapLegacy(m1)
0a5078
-    cm_m2 = CertmapLegacy(m2)
0a5078
-
0a5078
-    certmaps = cm_m1.list()
0a5078
-    certmaps['default']['DNComps'] = None
0a5078
-    certmaps['default']['CmapLdapAttr'] = 'nsCertSubjectDN'
0a5078
-
0a5078
-    cm_m1.set(certmaps)
0a5078
-    cm_m2.set(certmaps)
0a5078
-
0a5078
-    log.info('Enabling TLS')
0a5078
-    [i.enable_tls() for i in topology_m2]
0a5078
-
0a5078
-    log.info('Creating replication dns')
0a5078
-    services = ServiceAccounts(m1, DEFAULT_SUFFIX)
0a5078
-    repl_m1 = services.get('%s:%s' % (m1.host, m1.sslport))
0a5078
-    repl_m1.set('nsCertSubjectDN', m1.get_server_tls_subject())
0a5078
-
0a5078
-    repl_m2 = services.get('%s:%s' % (m2.host, m2.sslport))
0a5078
-    repl_m2.set('nsCertSubjectDN', m2.get_server_tls_subject())
0a5078
-
0a5078
-    log.info('Changing auth type')
0a5078
-    replica_m1 = Replicas(m1).get(DEFAULT_SUFFIX)
0a5078
-    agmt_m1 = replica_m1.get_agreements().list()[0]
0a5078
-    agmt_m1.replace_many(
0a5078
-        ('nsDS5ReplicaBindMethod', 'SSLCLIENTAUTH'),
0a5078
-        ('nsDS5ReplicaTransportInfo', 'SSL'),
0a5078
-        ('nsDS5ReplicaPort', '%s' % m2.sslport),
0a5078
-    )
0a5078
-
0a5078
-    agmt_m1.remove_all('nsDS5ReplicaBindDN')
0a5078
-
0a5078
-    replica_m2 = Replicas(m2).get(DEFAULT_SUFFIX)
0a5078
-    agmt_m2 = replica_m2.get_agreements().list()[0]
0a5078
-
0a5078
-    agmt_m2.replace_many(
0a5078
-        ('nsDS5ReplicaBindMethod', 'SSLCLIENTAUTH'),
0a5078
-        ('nsDS5ReplicaTransportInfo', 'SSL'),
0a5078
-        ('nsDS5ReplicaPort', '%s' % m1.sslport),
0a5078
-    )
0a5078
-    agmt_m2.remove_all('nsDS5ReplicaBindDN')
0a5078
-
0a5078
-    log.info('Stopping supplier2')
0a5078
-    m2.stop()
0a5078
-
0a5078
-    log.info('Run the cleanAllRUV task')
0a5078
-    cruv_task = CleanAllRUVTask(m1)
0a5078
-    cruv_task.create(properties={
0a5078
-        'replica-id': repl.get_rid(m1),
0a5078
-        'replica-base-dn': DEFAULT_SUFFIX,
0a5078
-        'replica-force-cleaning': 'no',
0a5078
-        'replica-certify-all': 'yes'
0a5078
-    })
0a5078
-
0a5078
-    m1.restart()
0a5078
-
0a5078
-    log.info('Check if supplier1 crashed')
0a5078
-    assert not m1.detectDisorderlyShutdown()
0a5078
-
0a5078
-    log.info('Repeat')
0a5078
-    m1.restart()
0a5078
-    assert not m1.detectDisorderlyShutdown()
0a5078
-
0a5078
 
0a5078
 if __name__ == '__main__':
0a5078
     # Run isolated
0a5078
diff --git a/dirsrvtests/tests/suites/replication/regression_m2_test.py b/dirsrvtests/tests/suites/replication/regression_m2_test.py
0a5078
index bbf9c8486..65c299a0c 100644
0a5078
--- a/dirsrvtests/tests/suites/replication/regression_m2_test.py
0a5078
+++ b/dirsrvtests/tests/suites/replication/regression_m2_test.py
0a5078
@@ -240,8 +240,12 @@ def test_double_delete(topo_m2, create_entry):
0a5078
     log.info('Deleting entry {} from supplier1'.format(create_entry.dn))
0a5078
     topo_m2.ms["supplier1"].delete_s(create_entry.dn)
0a5078
 
0a5078
-    log.info('Deleting entry {} from supplier2'.format(create_entry.dn))
0a5078
-    topo_m2.ms["supplier2"].delete_s(create_entry.dn)
0a5078
+    try:
0a5078
+        log.info('Deleting entry {} from supplier2'.format(create_entry.dn))
0a5078
+        topo_m2.ms["supplier2"].delete_s(create_entry.dn)
0a5078
+    except ldap.NO_SUCH_OBJECT:
0a5078
+        # replication was too fast (DEBUGGING is probably set)
0a5078
+        pass
0a5078
 
0a5078
     repl.enable_to_supplier(m2, [m1])
0a5078
     repl.enable_to_supplier(m1, [m2])
0a5078
@@ -813,8 +817,9 @@ def test_keepalive_entries(topo_m2):
0a5078
     keep_alive_s1 = str(entries[0].data['keepalivetimestamp'])
0a5078
     keep_alive_s2 = str(entries[1].data['keepalivetimestamp'])
0a5078
 
0a5078
-    # Wait for event interval (60 secs) to pass
0a5078
-    time.sleep(61)
0a5078
+    # Wait for event interval (60 secs) to pass, but first update doesn't
0a5078
+    # start until 30 seconds after startup
0a5078
+    time.sleep(91)
0a5078
 
0a5078
     # Check keep alives entries have been updated
0a5078
     entries = verify_keepalive_entries(topo_m2, True);
0a5078
diff --git a/dirsrvtests/tests/suites/replication/regression_m2c2_test.py b/dirsrvtests/tests/suites/replication/regression_m2c2_test.py
0a5078
index 97b35c7ab..f9de7383c 100644
0a5078
--- a/dirsrvtests/tests/suites/replication/regression_m2c2_test.py
0a5078
+++ b/dirsrvtests/tests/suites/replication/regression_m2c2_test.py
0a5078
@@ -289,6 +289,7 @@ def test_csngen_state_not_updated_if_different_uuid(topo_m2c2):
0a5078
         log.error(f"c1 csngen state has unexpectedly been synchronized with m2: time skew {c1_timeSkew}")
0a5078
         assert False
0a5078
     c1.start()
0a5078
+    time.sleep(5)
0a5078
 
0a5078
     # Step 8: Check that c2 has time skew
0a5078
     # Stop server to insure that dse.ldif is uptodate
0a5078
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
0a5078
index 5dab57de4..d67f1bc71 100644
0a5078
--- a/ldap/servers/plugins/replication/repl5_replica.c
0a5078
+++ b/ldap/servers/plugins/replication/repl5_replica.c
0a5078
@@ -239,8 +239,8 @@ replica_new_from_entry(Slapi_Entry *e, char *errortext, PRBool is_add_operation,
0a5078
     /* create supplier update event */
0a5078
     if (r->repl_eqcxt_ka_update == NULL && replica_get_type(r) == REPLICA_TYPE_UPDATABLE) {
0a5078
         r->repl_eqcxt_ka_update = slapi_eq_repeat_rel(replica_subentry_update, r,
0a5078
-                                                   slapi_current_rel_time_t() + 30,
0a5078
-                                                   replica_get_keepalive_update_interval(r));
0a5078
+                                                      slapi_current_rel_time_t() + 30,
0a5078
+                                                      1000 * replica_get_keepalive_update_interval(r));
0a5078
     }
0a5078
 
0a5078
     if (r->tombstone_reap_interval > 0) {
0a5078
@@ -518,7 +518,7 @@ replica_subentry_update(time_t when __attribute__((unused)), void *arg)
0a5078
     replica_subentry_check(repl_root, rid);
0a5078
 
0a5078
     slapi_timestamp_utc_hr(buf, SLAPI_TIMESTAMP_BUFSIZE);
0a5078
-    slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "replica_subentry_update called at %s\n", buf);
0a5078
+    slapi_log_err(SLAPI_LOG_REPL, "NSMMReplicationPlugin", "replica_subentry_update called at %s\n", buf);
0a5078
     val.bv_val = buf;
0a5078
     val.bv_len = strlen(val.bv_val);
0a5078
     vals[0] = &val;
0a5078
@@ -542,7 +542,7 @@ replica_subentry_update(time_t when __attribute__((unused)), void *arg)
0a5078
                       "Failure (%d) to update replication keep alive entry \"%s: %s\"\n",
0a5078
                       ldrc, KEEP_ALIVE_ATTR, buf);
0a5078
     } else {
0a5078
-        slapi_log_err(SLAPI_LOG_PLUGIN, repl_plugin_name,
0a5078
+        slapi_log_err(SLAPI_LOG_REPL, "NSMMReplicationPlugin",
0a5078
                       "replica_subentry_update - "
0a5078
                       "Successful update of replication keep alive entry \"%s: %s\"\n",
0a5078
                       KEEP_ALIVE_ATTR, buf);
0a5078
@@ -1536,7 +1536,7 @@ replica_set_enabled(Replica *r, PRBool enable)
0a5078
         if (r->repl_eqcxt_ka_update == NULL && replica_get_type(r) == REPLICA_TYPE_UPDATABLE) {
0a5078
             r->repl_eqcxt_ka_update = slapi_eq_repeat_rel(replica_subentry_update, r,
0a5078
                                                        slapi_current_rel_time_t() + START_UPDATE_DELAY,
0a5078
-                                                       replica_get_keepalive_update_interval(r));
0a5078
+                                                       1000 * replica_get_keepalive_update_interval(r));
0a5078
         }
0a5078
     } else /* disable */
0a5078
     {
0a5078
@@ -1546,7 +1546,7 @@ replica_set_enabled(Replica *r, PRBool enable)
0a5078
             r->repl_eqcxt_rs = NULL;
0a5078
         }
0a5078
         /* Remove supplier update event */
0a5078
-        if (replica_get_type(r) == REPLICA_TYPE_PRIMARY) {
0a5078
+        if (replica_get_type(r) == REPLICA_TYPE_UPDATABLE) {
0a5078
             slapi_eq_cancel_rel(r->repl_eqcxt_ka_update);
0a5078
             r->repl_eqcxt_ka_update = NULL;
0a5078
         }
0a5078
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
0a5078
index 70c45ec50..b32d00941 100644
0a5078
--- a/ldap/servers/plugins/replication/repl_extop.c
0a5078
+++ b/ldap/servers/plugins/replication/repl_extop.c
0a5078
@@ -493,7 +493,7 @@ free_and_return:
0a5078
         slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name,
0a5078
                 "decode_startrepl_extop - decoded csn: %s\n", *csnstr);
0a5078
         ruv_dump_to_log(*supplier_ruv, "decode_startrepl_extop");
0a5078
-        for (size_t i = 0; *extra_referrals && *extra_referrals[i]; i++) {
0a5078
+        for (size_t i = 0; *extra_referrals && extra_referrals[i]; i++) {
0a5078
             slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "decode_startrepl_extop - "
0a5078
                 "decoded referral: %s\n", *extra_referrals[i]);
0a5078
         }
0a5078
@@ -1661,7 +1661,7 @@ multimaster_extop_cleanruv(Slapi_PBlock *pb)
0a5078
          *  Launch the cleanruv monitoring thread.  Once all the replicas are cleaned it will release the rid
0a5078
          */
0a5078
 
0a5078
-        cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_ERR, "Launching cleanAllRUV thread...");
0a5078
+        cleanruv_log(NULL, rid, CLEANALLRUV_ID, SLAPI_LOG_INFO, "Launching cleanAllRUV thread...");
0a5078
         data = (cleanruv_data *)slapi_ch_calloc(1, sizeof(cleanruv_data));
0a5078
         if (data == NULL) {
0a5078
             slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "multimaster_extop_cleanruv - CleanAllRUV Task - Failed to allocate "
0a5078
diff --git a/ldap/servers/slapd/task.c b/ldap/servers/slapd/task.c
0a5078
index 4c7262ab3..71d5a2fb5 100644
0a5078
--- a/ldap/servers/slapd/task.c
0a5078
+++ b/ldap/servers/slapd/task.c
0a5078
@@ -742,7 +742,7 @@ get_internal_entry(Slapi_PBlock *pb, char *dn)
0a5078
     slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret;;
0a5078
     if (ret != LDAP_SUCCESS) {
0a5078
         slapi_log_err(SLAPI_LOG_WARNING, "get_internal_entry",
0a5078
-                      "Can't find task entry '%s'\n", dn);
0a5078
+                      "Failed to search for task entry '%s' error: %d\n", dn, ret);
0a5078
         return NULL;
0a5078
     }
0a5078
 
0a5078
@@ -786,9 +786,9 @@ modify_internal_entry(char *dn, LDAPMod **mods)
0a5078
              * entry -- try at least 3 times before giving up.
0a5078
              */
0a5078
             tries++;
0a5078
-            if (tries == 3) {
0a5078
-                slapi_log_err(SLAPI_LOG_WARNING, "modify_internal_entry", "Can't modify task "
0a5078
-                                                                          "entry '%s'; %s (%d)\n",
0a5078
+            if (tries == 5) {
0a5078
+                slapi_log_err(SLAPI_LOG_WARNING, "modify_internal_entry",
0a5078
+                              "Can't modify task entry '%s'; %s (%d)\n",
0a5078
                               dn, ldap_err2string(ret), ret);
0a5078
                 slapi_pblock_destroy(pb);
0a5078
                 return;
0a5078
diff --git a/src/lib389/lib389/instance/remove.py b/src/lib389/lib389/instance/remove.py
0a5078
index e96db3896..5668f375b 100644
0a5078
--- a/src/lib389/lib389/instance/remove.py
0a5078
+++ b/src/lib389/lib389/instance/remove.py
0a5078
@@ -90,6 +90,12 @@ def remove_ds_instance(dirsrv, force=False):
0a5078
     # Remove parent (/var/lib/dirsrv/slapd-INST)
0a5078
     shutil.rmtree(remove_paths['db_dir'].replace('db', ''), ignore_errors=True)
0a5078
 
0a5078
+    # Remove /run/slapd-isntance
0a5078
+    try:
0a5078
+        os.remove(f'/run/slapd-{dirsrv.serverid}.socket')
0a5078
+    except OSError as e:
0a5078
+        _log.debug("Failed to remove socket file: " + str(e))
0a5078
+
0a5078
     # We can not assume we have systemd ...
0a5078
     if dirsrv.ds_paths.with_systemd:
0a5078
         # Remove the systemd symlink
0a5078
-- 
0a5078
2.37.1
0a5078