Blame SOURCES/0001-Issue-50525-nsslapd-defaultnamingcontext-does-not-ch.patch

a3727e
From d33743c8604ff4f97947dad14fddab0691e3d19e Mon Sep 17 00:00:00 2001
a3727e
From: Mark Reynolds <mreynolds@redhat.com>
a3727e
Date: Thu, 1 Aug 2019 16:50:34 -0400
a3727e
Subject: [PATCH] Issue 50525 - nsslapd-defaultnamingcontext does not change
a3727e
 when the assigned suffix gets deleted
a3727e
a3727e
Bug Description:
a3727e
a3727e
If you delete the suffix that is set as the default naming context, the attribute
a3727e
is not reset.
a3727e
a3727e
Also using dsconf to delete a backend/suffix fails if there are vlv indexes, encrypted
a3727e
attributes, or replication is configured.
a3727e
a3727e
Fix Description:
a3727e
a3727e
As for the default naming context, if there is a second suffix configured, it will be
a3727e
automatically set as the new default naming context, otherwise the attribute is not
a3727e
modified.
a3727e
a3727e
For dsconf backend delete issue, it now checks and removes replication configuration
a3727e
and agreements, and removes all the child entries under the backend entry.
a3727e
a3727e
relates: https://pagure.io/389-ds-base/issue/50525
a3727e
a3727e
Reviewed by: spichugi(Thanks!)
a3727e
---
a3727e
 .../be_del_and_default_naming_attr_test.py    | 90 +++++++++++++++++++
a3727e
 ldap/servers/slapd/mapping_tree.c             | 50 ++++++-----
a3727e
 src/lib389/lib389/backend.py                  | 17 ++--
a3727e
 src/lib389/lib389/replica.py                  |  2 +-
a3727e
 4 files changed, 132 insertions(+), 27 deletions(-)
a3727e
 create mode 100644 dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py
a3727e
a3727e
diff --git a/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py b/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py
a3727e
new file mode 100644
a3727e
index 000000000..34a2de2ad
a3727e
--- /dev/null
a3727e
+++ b/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py
a3727e
@@ -0,0 +1,90 @@
a3727e
+import logging
a3727e
+import pytest
a3727e
+import os
a3727e
+from lib389._constants import DEFAULT_SUFFIX
a3727e
+from lib389.topologies import topology_m1 as topo
a3727e
+from lib389.backend import Backends
a3727e
+from lib389.encrypted_attributes import EncryptedAttrs
a3727e
+
a3727e
+DEBUGGING = os.getenv("DEBUGGING", default=False)
a3727e
+if DEBUGGING:
a3727e
+    logging.getLogger(__name__).setLevel(logging.DEBUG)
a3727e
+else:
a3727e
+    logging.getLogger(__name__).setLevel(logging.INFO)
a3727e
+log = logging.getLogger(__name__)
a3727e
+
a3727e
+SECOND_SUFFIX = 'o=namingcontext'
a3727e
+THIRD_SUFFIX = 'o=namingcontext2'
a3727e
+
a3727e
+def test_be_delete(topo):
a3727e
+    """Test that we can delete a backend that contains replication
a3727e
+    configuration and encrypted attributes.  The default naming 
a3727e
+    context should also be updated to reflect the next available suffix
a3727e
+
a3727e
+    :id: 5208f897-7c95-4925-bad0-9ceb95fee678
a3727e
+    :setup: Master Instance
a3727e
+    :steps:
a3727e
+        1. Create second backend/suffix
a3727e
+        2. Add an encrypted attribute to the default suffix
a3727e
+        2. Delete default suffix
a3727e
+        3. Check the nsslapd-defaultnamingcontext is updated
a3727e
+        4. Delete the last backend
a3727e
+        5. Check the namingcontext has not changed
a3727e
+        6. Add new backend
a3727e
+        7. Set default naming context
a3727e
+        8. Verify the naming context is correct
a3727e
+    :expectedresults:
a3727e
+        1. Success
a3727e
+        2. Success
a3727e
+        3. Success
a3727e
+        4. Success
a3727e
+        5. Success
a3727e
+        6. Success
a3727e
+        7. Success
a3727e
+        8. Success
a3727e
+    """
a3727e
+    
a3727e
+    inst = topo.ms["master1"] 
a3727e
+    
a3727e
+    # Create second suffix      
a3727e
+    backends = Backends(inst)
a3727e
+    default_backend = backends.get(DEFAULT_SUFFIX)
a3727e
+    new_backend = backends.create(properties={'nsslapd-suffix': SECOND_SUFFIX,
a3727e
+                                              'name': 'namingRoot'})
a3727e
+  
a3727e
+    # Add encrypted attribute entry under default suffix
a3727e
+    encrypt_attrs = EncryptedAttrs(inst, basedn='cn=encrypted attributes,{}'.format(default_backend.dn))
a3727e
+    encrypt_attrs.create(properties={'cn': 'employeeNumber', 'nsEncryptionAlgorithm': 'AES'})
a3727e
+    
a3727e
+    # Delete default suffix
a3727e
+    default_backend.delete()
a3727e
+    
a3727e
+    # Check that the default naming context is set to the new/second suffix
a3727e
+    default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext')
a3727e
+    assert default_naming_ctx == SECOND_SUFFIX
a3727e
+
a3727e
+    # delete new backend, but the naming context should not change
a3727e
+    new_backend.delete()
a3727e
+
a3727e
+    # Check that the default naming context is still set to the new/second suffix
a3727e
+    default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext')
a3727e
+    assert default_naming_ctx == SECOND_SUFFIX
a3727e
+
a3727e
+    # Add new backend
a3727e
+    new_backend = backends.create(properties={'nsslapd-suffix': THIRD_SUFFIX,
a3727e
+                                              'name': 'namingRoot2'})
a3727e
+
a3727e
+    # manaully set naming context
a3727e
+    inst.config.set('nsslapd-defaultnamingcontext', THIRD_SUFFIX)
a3727e
+
a3727e
+    # Verify naming context is correct
a3727e
+    default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext')
a3727e
+    assert default_naming_ctx == THIRD_SUFFIX
a3727e
+
a3727e
+
a3727e
+if __name__ == '__main__':
a3727e
+    # Run isolated
a3727e
+    # -s for DEBUG mode
a3727e
+    CURRENT_FILE = os.path.realpath(__file__)
a3727e
+    pytest.main(["-s", CURRENT_FILE])
a3727e
+
a3727e
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
a3727e
index 834949a67..25e9fb80c 100644
a3727e
--- a/ldap/servers/slapd/mapping_tree.c
a3727e
+++ b/ldap/servers/slapd/mapping_tree.c
a3727e
@@ -1521,26 +1521,36 @@ done:
a3727e
                 strcpy_unescape_value(escaped, suffix);
a3727e
             }
a3727e
             if (escaped && (0 == strcasecmp(escaped, default_naming_context))) {
a3727e
-                int rc = _mtn_update_config_param(LDAP_MOD_DELETE,
a3727e
-                                                  CONFIG_DEFAULT_NAMING_CONTEXT,
a3727e
-                                                  NULL);
a3727e
-                if (rc) {
a3727e
-                    slapi_log_err(SLAPI_LOG_ERR,
a3727e
-                                  "mapping_tree_entry_delete_callback",
a3727e
-                                  "deleting config param %s failed: RC=%d\n",
a3727e
-                                  CONFIG_DEFAULT_NAMING_CONTEXT, rc);
a3727e
-                }
a3727e
-                if (LDAP_SUCCESS == rc) {
a3727e
-                    char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE] = {0};
a3727e
-                    /* Removing defaultNamingContext from cn=config entry
a3727e
-                     * was successful.  The remove does not reset the
a3727e
-                     * global parameter.  We need to reset it separately. */
a3727e
-                    if (config_set_default_naming_context(
a3727e
-                            CONFIG_DEFAULT_NAMING_CONTEXT,
a3727e
-                            NULL, errorbuf, CONFIG_APPLY)) {
a3727e
-                        slapi_log_err(SLAPI_LOG_ERR, "mapping_tree_entry_delete_callback",
a3727e
-                                      "Setting NULL to %s failed. %s\n",
a3727e
-                                      CONFIG_DEFAULT_NAMING_CONTEXT, errorbuf);
a3727e
+                /*
a3727e
+                 * We can not delete the default naming attribute, so instead
a3727e
+                 * replace it only if there is another suffix available
a3727e
+                 */
a3727e
+                void *node = NULL;
a3727e
+                Slapi_DN *sdn;
a3727e
+                sdn = slapi_get_first_suffix(&node, 0);
a3727e
+                if (sdn) {
a3727e
+                    char *replacement_suffix = (char *)slapi_sdn_get_dn(sdn);
a3727e
+                    int rc = _mtn_update_config_param(LDAP_MOD_REPLACE,
a3727e
+                                                      CONFIG_DEFAULT_NAMING_CONTEXT,
a3727e
+                                                      replacement_suffix);
a3727e
+                    if (rc) {
a3727e
+                        slapi_log_err(SLAPI_LOG_ERR,
a3727e
+                                      "mapping_tree_entry_delete_callback",
a3727e
+                                      "replacing config param %s failed: RC=%d\n",
a3727e
+                                      CONFIG_DEFAULT_NAMING_CONTEXT, rc);
a3727e
+                    }
a3727e
+                    if (LDAP_SUCCESS == rc) {
a3727e
+                        char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE] = {0};
a3727e
+                        /* Replacing defaultNamingContext from cn=config entry
a3727e
+                         * was successful.  The replace does not reset the
a3727e
+                         * global parameter.  We need to reset it separately. */
a3727e
+                        if (config_set_default_naming_context(
a3727e
+                                CONFIG_DEFAULT_NAMING_CONTEXT,
a3727e
+                                replacement_suffix, errorbuf, CONFIG_APPLY)) {
a3727e
+                            slapi_log_err(SLAPI_LOG_ERR, "mapping_tree_entry_delete_callback",
a3727e
+                                          "Setting %s tp %s failed. %s\n",
a3727e
+                                          CONFIG_DEFAULT_NAMING_CONTEXT, replacement_suffix, errorbuf);
a3727e
+                        }
a3727e
                     }
a3727e
                 }
a3727e
             }
a3727e
diff --git a/src/lib389/lib389/backend.py b/src/lib389/lib389/backend.py
a3727e
index 6f4c8694e..4d32038f6 100644
a3727e
--- a/src/lib389/lib389/backend.py
a3727e
+++ b/src/lib389/lib389/backend.py
a3727e
@@ -17,6 +17,7 @@ from lib389 import Entry
a3727e
 from lib389._mapped_object import DSLdapObjects, DSLdapObject
a3727e
 from lib389.mappingTree import MappingTrees, MappingTree
a3727e
 from lib389.exceptions import NoSuchEntryError, InvalidArgumentError
a3727e
+from lib389.replica import Replicas
a3727e
 
a3727e
 # We need to be a factor to the backend monitor
a3727e
 from lib389.monitor import MonitorBackend
a3727e
@@ -507,20 +508,24 @@ class Backend(DSLdapObject):
a3727e
             mt = self._mts.get(selector=bename)
a3727e
             # Assert the type is "backend"
a3727e
             # Are these the right types....?
a3727e
-            if mt.get_attr_val('nsslapd-state') != ensure_bytes('backend'):
a3727e
+            if mt.get_attr_val('nsslapd-state').lower() != ensure_bytes('backend'):
a3727e
                 raise ldap.UNWILLING_TO_PERFORM('Can not delete the mapping tree, not for a backend! You may need to delete this backend via cn=config .... ;_; ')
a3727e
+
a3727e
+            # Delete replicas first
a3727e
+            try:
a3727e
+                Replicas(self._instance).get(mt.get_attr_val_utf8('cn')).delete()
a3727e
+            except ldap.NO_SUCH_OBJECT:
a3727e
+                # No replica, no problem
a3727e
+                pass
a3727e
+
a3727e
             # Delete our mapping tree if it exists.
a3727e
             mt.delete()
a3727e
         except ldap.NO_SUCH_OBJECT:
a3727e
             # Righto, it's already gone! Do nothing ...
a3727e
             pass
a3727e
-        # Delete all our related indices
a3727e
-        self._instance.index.delete_all(bename)
a3727e
 
a3727e
         # Now remove our children, this is all ldbm config
a3727e
-        self._instance.delete_branch_s(self._dn, ldap.SCOPE_ONELEVEL)
a3727e
-        # The super will actually delete ourselves.
a3727e
-        super(Backend, self).delete()
a3727e
+        self._instance.delete_branch_s(self._dn, ldap.SCOPE_SUBTREE)
a3727e
 
a3727e
     def _lint_mappingtree(self):
a3727e
         """Backend lint
a3727e
diff --git a/src/lib389/lib389/replica.py b/src/lib389/lib389/replica.py
a3727e
index cdd0a9729..7b45683d9 100644
a3727e
--- a/src/lib389/lib389/replica.py
a3727e
+++ b/src/lib389/lib389/replica.py
a3727e
@@ -458,7 +458,7 @@ class ReplicaLegacy(object):
a3727e
         try:
a3727e
             self.deleteAgreements(nsuffix)
a3727e
         except ldap.LDAPError as e:
a3727e
-            self.log.fatal('Failed to delete replica agreements!')
a3727e
+            self.log.fatal('Failed to delete replica agreements!  ' + str(e))
a3727e
             raise
a3727e
 
a3727e
         # Delete the replica
a3727e
-- 
a3727e
2.21.0
a3727e