From 9f9b33fcec471e3a13095ee82d1fcdc5b7247854 Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbor...@redhat.com>
Date: Wed, 20 Jan 2016 15:31:58 +0100
Subject: [PATCH] configure DNA plugin shared config entries to allow
 connection with GSSAPI

When a replica needs to extend its DNA range, it selects the remote replica with the
larger available range. If there is no replica agreement to that remote replica,
the shared config entry needs to contain the connection method/protocol
---
 ipaserver/install/server/install.py        |  4 ++
 ipaserver/install/server/replicainstall.py |  8 ++++
 ipaserver/install/service.py               | 63 ++++++++++++++++++++++++++++++
 ipaserver/install/upgradeinstance.py       |  6 ++-
 4 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
index 49e97eb667a322898acc3a064f4eae5381ded918..64994f3ea676d76e9c58c57fdbbf397711424375 100644
--- a/ipaserver/install/server/install.py
+++ b/ipaserver/install/server/install.py
@@ -955,6 +955,10 @@ def install(installer):
     service.print_msg("Restarting the web server")
     http.restart()
 
+    #update DNA shared config entry is done as far as possible
+    #from restart to avoid waiting for its creation
+    ds.update_dna_shared_config()
+
     # Set the admin user kerberos password
     ds.change_admin_password(admin_password)
 
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index 41d14f5801ba1cefaca7a27f78d64f45017805a2..1d4e6a23ed443af9963194909d7819076d07d855 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -809,6 +809,10 @@ def install(installer):
 
     ds.replica_populate()
 
+    #update DNA shared config entry is done as far as possible
+    #from restart to avoid waiting for its creation
+    ds.update_dna_shared_config()
+
     # Everything installed properly, activate ipa service.
     services.knownservices.ipa.enable()
 
@@ -1375,6 +1379,10 @@ def promote(installer):
 
     ds.replica_populate()
 
+    #update DNA shared config entry is done as far as possible
+    #from restart to avoid waiting for its creation
+    ds.update_dna_shared_config()
+
     custodia.import_dm_password(config.master_host_name)
 
     promote_sssd(config.host_name)
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index c77a4cc461f6a63033753e06736156460de8eafa..ec47c3281cbda3079268c0ac5bbc96a5574b723e 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -22,6 +22,8 @@ import os, socket
 import tempfile
 import datetime
 import traceback
+import ldap
+import time
 
 from ipapython import sysrestore, ipautil, ipaldap
 from ipapython.dn import DN
@@ -183,6 +185,67 @@ class Service(object):
         self.admin_conn.unbind()
         self.admin_conn = None
 
+    def update_dna_shared_config(self, method="SASL/GSSAPI", protocol="LDAP"):
+
+        DNA_BIND_METHOD   = "dnaRemoteBindMethod"
+        DNA_CONN_PROTOCOL = "dnaRemoteConnProtocol"
+        DNA_PLUGIN_DN     = 'cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config'
+        dna_config_base   = 'cn=Posix IDs,%s' % DNA_PLUGIN_DN
+        if not self.admin_conn:
+            self.ldap_connect()
+        conn = self.admin_conn
+
+        try:
+            entry = conn.get_entry(DN(dna_config_base))
+        except errors.NotFound:
+            root_logger.error("Could not find DNA config entry: %s" % (dna_config_base))
+            return
+
+        sharedcfgdn = entry.single_value.get("dnaSharedCfgDN")
+        if sharedcfgdn is not None:
+            sharedcfgdn = DN(sharedcfgdn)
+        else:
+            root_logger.error("Could not find DNA shared config DN in entry: %s" % (dna_config_base))
+            return
+
+        # a server waits for 30s after its startup to update its shared config
+        MAX_WAIT=30
+        attempt=0
+        while attempt != MAX_WAIT:
+            try:
+                entries = conn.get_entries(sharedcfgdn, scope=ldap.SCOPE_ONELEVEL, filter='dnaHostname=%s' % self.fqdn)
+                break
+            except errors.NotFound:
+                root_logger.debug("So far enable not find DNA shared config entry for dnaHostname=%s under %s. Retry in 2sec" % (self.fqdn, sharedcfgdn))
+                attempt = attempt + 1
+                time.sleep(2)
+                continue
+
+        # safety checking
+        # there is no return, if there are several entries, as a workaround of #5510
+        if len(entries) != 1:
+            root_logger.debug("%d entries dnaHostname=%s under %s. One expected" % (len(entries), self.fqdn, sharedcfgdn))
+
+        # time to set the bind method and protocol in the shared config entries
+
+        for i in range(len(entries)) :
+
+            mod = []
+            if entries[i].single_value.get(DNA_BIND_METHOD) != method:
+                mod.append((ldap.MOD_REPLACE, DNA_BIND_METHOD, method))
+
+            if entries[i].single_value.get(DNA_CONN_PROTOCOL) != protocol:
+                mod.append((ldap.MOD_REPLACE, DNA_CONN_PROTOCOL, protocol))
+
+            if len(mod) > 0:
+                conn.modify_s(entries[i].dn, mod)
+                entry = conn.get_entry(entries[i].dn)
+                if entry.single_value.get(DNA_BIND_METHOD) != method:
+                    root_logger.error("Fail to set SASL/GSSAPI bind method to %s" % (entries[i].dn))
+                if entry.single_value.get(DNA_CONN_PROTOCOL) != protocol:
+                    root_logger.error("Fail to set LDAP protocol to %s" % (entries[i].dn))
+
+
     def _ldap_mod(self, ldif, sub_dict=None, raise_on_err=False):
         pw_name = None
         fd = None
diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py
index 81e3beb8ef48915f36507c548d008e988d4e3868..dc84c1467b73789260889d759d03096c7f779ddb 100644
--- a/ipaserver/install/upgradeinstance.py
+++ b/ipaserver/install/upgradeinstance.py
@@ -113,8 +113,10 @@ class IPAUpgrade(service.Service):
                   run_after_failure=True)
         self.step("restoring configuration", self.__restore_config,
                   run_after_failure=True)
-        if ds_running:
-            self.step("starting directory server", self.start)
+        self.step("starting directory server", self.start)
+        self.step("update DNA shared config entry", self.update_dna_shared_config)
+        if not ds_running:
+            self.step("stopping directory server", self.__stop_instance)
         self.start_creation(start_message="Upgrading IPA:",
                             show_service_name=False)
 
-- 
1.7.11.7

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to