URL: https://github.com/freeipa/freeipa/pull/2111 Author: tiran Title: #2111: Tune DS replication settings Action: opened
PR body: """ Tune 389-DS replication settings to improve performance and avoid timeouts. During installation of a replica, the value of nsDS5ReplicaBindDnGroupCheckInterval is reduced to 2 seconds. At the end of the installation, the value is increased sensible production settings. This avoids long delays during replication. See: https://pagure.io/freeipa/issue/7617 Signed-off-by: Christian Heimes <chei...@redhat.com> """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/2111/head:pr2111 git checkout pr2111
From 5de55b1014647dca09b6e111771af4241a69a722 Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Tue, 3 Jul 2018 19:40:05 +0200 Subject: [PATCH] Tune DS replication settings Tune 389-DS replication settings to improve performance and avoid timeouts. During installation of a replica, the value of nsDS5ReplicaBindDnGroupCheckInterval is reduced to 2 seconds. At the end of the installation, the value is increased sensible production settings. This avoids long delays during replication. See: https://pagure.io/freeipa/issue/7617 Signed-off-by: Christian Heimes <chei...@redhat.com> --- ipaserver/install/cainstance.py | 7 ++- ipaserver/install/dsinstance.py | 48 ++++++++++------- ipaserver/install/replication.py | 74 +++++++++++++++++++-------- ipaserver/install/server/replicainstall.py | 2 + ipaserver/install/server/upgrade.py | 14 +++-- ipatests/test_integration/test_external_ca.py | 5 +- 6 files changed, 106 insertions(+), 44 deletions(-) diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 0fcd579d1c..313809df14 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -419,6 +419,8 @@ def configure_instance(self, host_name, dm_password, admin_password, self.teardown_admin) self.step("starting certificate server instance", self.start_instance) + self.step("Finalize replication settings", + self.finalize_replica_config) # Step 1 of external is getting a CSR so we don't need to do these # steps until we get a cert back from the external CA. if self.external != 1: @@ -1253,13 +1255,16 @@ def __create_ds_db(self): api.Backend.ldap2.add_entry(entry) def __setup_replication(self): - repl = replication.CAReplicationManager(self.realm, self.fqdn) repl.setup_cs_replication(self.master_host) # Activate Topology for o=ipaca segments self.__update_topology() + def finalize_replica_config(self): + repl = replication.CAReplicationManager(self.realm, self.fqdn) + repl.finalize_replica_config(self.master_host) + def __enable_instance(self): basedn = ipautil.realm_to_suffix(self.realm) if not self.clone: diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index d00799a47d..492bc67474 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -418,6 +418,20 @@ def create_replica(self, realm_name, master_fqdn, fqdn, self.start_creation(runtime=30) + def _get_replication_manager(self): + # Always connect to self over ldapi + ldap_uri = ipaldap.get_ldap_uri(protocol='ldapi', realm=self.realm) + conn = ipaldap.LDAPClient(ldap_uri) + conn.external_bind() + repl = replication.ReplicationManager( + self.realm, self.fqdn, self.dm_password, conn=conn + ) + if self.dm_password is not None and not self.promote: + bind_dn = DN(('cn', 'Directory Manager')) + bind_pw = self.dm_password + else: + bind_dn = bind_pw = None + return repl, bind_dn, bind_pw def __setup_replica(self): """ @@ -434,26 +448,24 @@ def __setup_replica(self): self.realm, self.dm_password) - # Always connect to self over ldapi - ldap_uri = ipaldap.get_ldap_uri(protocol='ldapi', realm=self.realm) - conn = ipaldap.LDAPClient(ldap_uri) - conn.external_bind() - repl = replication.ReplicationManager(self.realm, - self.fqdn, - self.dm_password, conn=conn) - - if self.dm_password is not None and not self.promote: - bind_dn = DN(('cn', 'Directory Manager')) - bind_pw = self.dm_password - else: - bind_dn = bind_pw = None - - repl.setup_promote_replication(self.master_fqdn, - r_binddn=bind_dn, - r_bindpw=bind_pw, - cacert=self.ca_file) + repl, bind_dn, bind_pw = self._get_replication_manager() + repl.setup_promote_replication( + self.master_fqdn, + r_binddn=bind_dn, + r_bindpw=bind_pw, + cacert=self.ca_file + ) self.run_init_memberof = repl.needs_memberof_fixup() + def finalize_replica_config(self): + repl, bind_dn, bind_pw = self._get_replication_manager() + repl.finalize_replica_config( + self.master_fqdn, + r_binddn=bind_dn, + r_bindpw=bind_pw, + cacert=self.ca_file + ) + def __configure_sasl_mappings(self): # we need to remove any existing SASL mappings in the directory as otherwise they # they may conflict. diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py index 5ce8fa689c..435786de42 100644 --- a/ipaserver/install/replication.py +++ b/ipaserver/install/replication.py @@ -75,6 +75,17 @@ 'internalModifiersName', 'internalModifyTimestamp') +# settings for cn=replica,cn=$DB,cn=mapping tree,cn=config +# during replica installation +REPLICA_CREATION_SETTINGS = { + "nsds5ReplicaReleaseTimeout": ["20"], + "nsds5ReplicaBackoffMax": ["3"], + "nsDS5ReplicaBindDnGroupCheckInterval": ["2"] +} +# after replica installation +REPLICA_FINAL_SETTINGS = REPLICA_CREATION_SETTINGS.copy() +REPLICA_FINAL_SETTINGS["nsDS5ReplicaBindDnGroupCheckInterval"] = ["60"] + def replica_conn_check(master_host, host_name, realm, check_ca, dogtag_master_ds_port, admin_password=None, @@ -201,9 +212,13 @@ def wait_for_entry(connection, dn, timeout, attr=None, attrvalue='*', class ReplicationManager(object): - """Manage replication agreements between DS servers, and sync - agreements with Windows servers""" - def __init__(self, realm, hostname, dirman_passwd, port=PORT, starttls=False, conn=None): + """Manage replication agreements + + between DS servers, and sync agreements with Windows servers + """ + + def __init__(self, realm, hostname, dirman_passwd=None, port=PORT, + starttls=False, conn=None): self.hostname = hostname self.port = port self.dirman_passwd = dirman_passwd @@ -481,22 +496,16 @@ def replica_config(self, conn, replica_id, replica_binddn): except errors.NotFound: pass else: - managers = {DN(m) for m in entry.get('nsDS5ReplicaBindDN', [])} - - mods = [] - if replica_binddn not in managers: + binddns = entry.setdefault('nsDS5ReplicaBindDN', []) + if replica_binddn not in {DN(m) for m in binddns}: # Add the new replication manager - mods.append( - (ldap.MOD_ADD, 'nsDS5ReplicaBindDN', replica_binddn) - ) - if 'nsds5replicareleasetimeout' not in entry: - # See https://pagure.io/freeipa/issue/7488 - mods.append( - (ldap.MOD_ADD, 'nsds5replicareleasetimeout', ['60']) - ) - - if mods: - conn.modify_s(dn, mods) + binddns.append(replica_binddn) + for key, value in REPLICA_CREATION_SETTINGS.items(): + entry[key] = value + try: + conn.update_entry(entry) + except errors.EmptyModlist: + pass self.set_replica_binddngroup(conn, entry) @@ -515,9 +524,8 @@ def replica_config(self, conn, replica_id, replica_binddn): nsds5flags=["1"], nsds5replicabinddn=[replica_binddn], nsds5replicabinddngroup=[self.repl_man_group_dn], - nsds5replicabinddngroupcheckinterval=["60"], - nsds5replicareleasetimeout=["60"], nsds5replicalegacyconsumer=["off"], + **REPLICA_CREATION_SETTINGS, ) conn.add_entry(entry) @@ -543,6 +551,32 @@ def setup_changelog(self, conn): except errors.DuplicateEntry: return + def _finalize_replica_config(self, conn): + """Change replica settings to final values + + During replica installation, some settings are configured for faster + replication. + """ + dn = self.replica_dn() + entry = conn.get_entry(dn) + for key, value in REPLICA_FINAL_SETTINGS.items(): + entry[key] = value + try: + conn.update_entry(entry) + except errors.EmptyModlist: + pass + + def finalize_replica_config(self, r_hostname, r_binddn=None, + r_bindpw=None, cacert=paths.IPA_CA_CRT): + ldap_uri = ipaldap.get_ldap_uri(r_hostname) + r_conn = ipaldap.LDAPClient(ldap_uri, cacert=cacert) + if r_bindpw: + r_conn.simple_bind(r_binddn, r_bindpw) + else: + r_conn.gssapi_bind() + self._finalize_replica_config(self.conn) + self.finalize_replica_config(r_conn) + def setup_chaining_backend(self, conn): chaindn = DN(('cn', 'chaining database'), ('cn', 'plugins'), ('cn', 'config')) benamebase = "chaindb" diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 3ec2d6526a..b29d64e815 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -1505,6 +1505,8 @@ def install(installer): # Apply any LDAP updates. Needs to be done after the replica is synced-up service.print_msg("Applying LDAP updates") ds.apply_updates() + service.print_msg("Finalize replication settings") + ds.finalize_replica_config() if kra_enabled: kra.install(api, config, options, custodia=custodia) diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index 0fe3dd10a7..4b59d78cb9 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -48,6 +48,7 @@ from ipaserver.install import dogtaginstance from ipaserver.install import krbinstance from ipaserver.install import adtrustinstance +from ipaserver.install import replication from ipaserver.install.upgradeinstance import IPAUpgrade from ipaserver.install.ldapupdate import BadSyntax @@ -1680,11 +1681,16 @@ def update_replica_config(db_suffix): except ipalib.errors.NotFound: return # entry does not exist until a replica is installed - if 'nsds5replicareleasetimeout' not in entry: - # See https://pagure.io/freeipa/issue/7488 - logger.info("Adding nsds5replicaReleaseTimeout=60 to %s", dn) - entry['nsds5replicareleasetimeout'] = '60' + for key, value in replication.REPLICA_FINAL_SETTINGS.items(): + if entry.get(key) != value: + entry[key] = value + + try: api.Backend.ldap2.update_entry(entry) + except ipalib.errors.EmptyModlist: + pass + else: + logger.info("Updated entry %s", dn) def migrate_to_authselect(): diff --git a/ipatests/test_integration/test_external_ca.py b/ipatests/test_integration/test_external_ca.py index 5a7aa16123..60cd643545 100644 --- a/ipatests/test_integration/test_external_ca.py +++ b/ipatests/test_integration/test_external_ca.py @@ -148,7 +148,10 @@ def test_external_ca(self): '-LLL', '-o', 'ldif-wrap=no']) - assert 'nsds5ReplicaReleaseTimeout: 60' in result.stdout_text + # case insensitive match + text = result.stdout_text.lower() + assert 'nsds5ReplicaReleaseTimeout: 20'.lower() in text + assert 'nsDS5ReplicaBindDnGroupCheckInterval: 60'.lower() in text def test_client_installation_with_otp(self): # Test for issue 7526: client installation fails with one-time
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/freeipa-devel@lists.fedorahosted.org/message/FR6SFTKXFMUSVWPSWIYRHNDOPX6YNHXG/