URL: https://github.com/freeipa/freeipa/pull/872
Author: stlaz
 Title: #872: Add IPA-specific bind unit file
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/872/head:pr872
git checkout pr872
From c8f0060ce4ac27db4db1771a65b9319fb6557cdc Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka <slazn...@redhat.com>
Date: Wed, 14 Jun 2017 07:46:16 +0200
Subject: [PATCH] Add IPA-specific bind unit file

During upgrade of Fedora 25 to 26, when FreeIPA is installed with
DNS, bind attempts to start before KDC which leads to a failed
start because it requires a ticket to connect to LDAP.

Add an own unit file with a dependency which sets bind to start
after the KDC service.

https://pagure.io/freeipa/issue/7018
---
 freeipa.spec.in                              |  1 +
 init/systemd/Makefile.am                     |  2 +
 init/systemd/ipa-named-pkcs11.service.in     | 27 ++++++++++++
 ipaplatform/redhat/services.py               |  3 +-
 ipaserver/install/bindinstance.py            | 66 ++++++++++++++++------------
 ipaserver/install/server/upgrade.py          | 45 +++++++++++++++++--
 ipatests/pytest_plugins/integration/tasks.py |  4 +-
 ipatests/test_xmlrpc/test_location_plugin.py |  4 +-
 8 files changed, 114 insertions(+), 38 deletions(-)
 create mode 100644 init/systemd/ipa-named-pkcs11.service.in

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 1446dfbb7c..00b2bb8ae1 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -1220,6 +1220,7 @@ fi
 %attr(644,root,root) %{_unitdir}/ipa-dnskeysyncd.service
 %attr(644,root,root) %{_unitdir}/ipa-ods-exporter.socket
 %attr(644,root,root) %{_unitdir}/ipa-ods-exporter.service
+%attr(644,root,root) %{_unitdir}/ipa-named-pkcs11.service
 # END
 %attr(755,root,root) %{plugin_dir}/libipa_pwd_extop.so
 %attr(755,root,root) %{plugin_dir}/libipa_enrollment_extop.so
diff --git a/init/systemd/Makefile.am b/init/systemd/Makefile.am
index 945f6ac22a..c417caac87 100644
--- a/init/systemd/Makefile.am
+++ b/init/systemd/Makefile.am
@@ -3,10 +3,12 @@
 AUTOMAKE_OPTIONS = 1.7
 
 dist_noinst_DATA = 			\
+	ipa-named-pkcs11.service.in \
 	ipa-custodia.service.in		\
 	ipa.service.in
 
 systemdsystemunit_DATA = 	\
+	ipa-named-pkcs11.service \
 	ipa-custodia.service	\
 	ipa.service
 
diff --git a/init/systemd/ipa-named-pkcs11.service.in b/init/systemd/ipa-named-pkcs11.service.in
new file mode 100644
index 0000000000..d89d9976e5
--- /dev/null
+++ b/init/systemd/ipa-named-pkcs11.service.in
@@ -0,0 +1,27 @@
+[Unit]
+Description=Berkeley Internet Name Domain (DNS) with native PKCS#11
+Wants=nss-lookup.target
+Wants=named-setup-rndc.service
+Before=nss-lookup.target
+After=network.target
+After=named-setup-rndc.service
+# we need to wait for KDC so that named may connect to LDAP via GSSAPI
+After=krb5kdc.service
+
+[Service]
+Type=forking
+EnvironmentFile=-/etc/sysconfig/named
+Environment=KRB5_KTNAME=/etc/named.keytab
+PIDFile=/run/named/named.pid
+
+ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z /etc/named.conf; else echo "Checking of zone files is disabled"; fi'
+ExecStart=/usr/sbin/named-pkcs11 -u named $OPTIONS
+
+ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID'
+
+ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID'
+
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ipaplatform/redhat/services.py b/ipaplatform/redhat/services.py
index 8fae1f3cc5..ee5060e28f 100644
--- a/ipaplatform/redhat/services.py
+++ b/ipaplatform/redhat/services.py
@@ -62,7 +62,8 @@
 redhat_system_units['ipa-otpd'] = 'ipa-otpd.socket'
 redhat_system_units['ipa-dnskeysyncd'] = 'ipa-dnskeysyncd.service'
 redhat_system_units['named-regular'] = 'named.service'
-redhat_system_units['named-pkcs11'] = 'named-pkcs11.service'
+redhat_system_units['named-pkcs11-regular'] = 'named-pkcs11.service'
+redhat_system_units['named-pkcs11'] = 'ipa-named-pkcs11.service'
 redhat_system_units['named'] = redhat_system_units['named-pkcs11']
 redhat_system_units['ods-enforcerd'] = 'ods-enforcerd.service'
 redhat_system_units['ods_enforcerd'] = redhat_system_units['ods-enforcerd']
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 03dce56aa0..dbc014303e 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -619,7 +619,11 @@ def __init__(self, fstore=None, api=api):
         self.forwarders = None
         self.sub_dict = None
         self.reverse_zones = []
-        self.named_regular = services.service('named-regular', api)
+        # these DNS services should be disabled prior to setting up our own
+        self.regular_dns_services = {
+            'named': services.service('named-regular', api),
+            'named-pkcs11': services.service('named-pkcs11-regular', api)
+        }
 
     suffix = ipautil.dn_attribute_property('_suffix')
 
@@ -735,8 +739,9 @@ def __start(self):
     def __enable(self):
         if self.get_state("enabled") is None:
             self.backup_state("enabled", self.is_running())
-            self.backup_state("named-regular-enabled",
-                              self.named_regular.is_running())
+            for svc_name, svc in self.regular_dns_services.items():
+                self.backup_state("{}-regular-enabled".format(svc_name),
+                                  svc.is_running())
         # We do not let the system start IPA components on its own,
         # Instead we reply on the IPA init script to start only enabled
         # components as found in our LDAP configuration tree
@@ -747,20 +752,24 @@ def __enable(self):
             # don't crash, just report error
             root_logger.error("DNS service already exists")
 
-        # disable named, we need to run named-pkcs11 only
-        if self.get_state("named-regular-running") is None:
-            # first time store status
-            self.backup_state("named-regular-running",
-                              self.named_regular.is_running())
-        try:
-            self.named_regular.stop()
-        except Exception as e:
-            root_logger.debug("Unable to stop named (%s)", e)
-
-        try:
-            self.named_regular.mask()
-        except Exception as e:
-            root_logger.debug("Unable to mask named (%s)", e)
+        for svc_name, svc in self.regular_dns_services.items():
+            # disable named, we need to run named-pkcs11 only
+            if self.get_state("{}-regular-running".format(svc_name)) is None:
+                # first time store status
+                self.backup_state("{}-regular-running".format(svc_name),
+                                  svc.is_running())
+            try:
+                svc.stop()
+            except Exception as e:
+                root_logger.debug(
+                    "Unable to stop {name} ({err})"
+                    .format(name=svc_name, err=e))
+            try:
+                svc.mask()
+            except Exception as e:
+                root_logger.debug(
+                    "Unable to mask {name} ({err})"
+                    .format(name=svc_name, err=e))
 
     def __setup_sub_dict(self):
         self.sub_dict = dict(
@@ -1163,31 +1172,30 @@ def uninstall(self):
 
         running = self.restore_state("running")
         enabled = self.restore_state("enabled")
-        named_regular_running = self.restore_state("named-regular-running")
-        named_regular_enabled = self.restore_state("named-regular-enabled")
 
         self.dns_backup.clear_records(self.api.Backend.ldap2.isconnected())
-
-
         for f in [NAMED_CONF, RESOLV_CONF]:
             try:
                 self.fstore.restore_file(f)
             except ValueError as error:
                 root_logger.debug(error)
-
         # disabled by default, by ldap_enable()
         if enabled:
             self.enable()
-
         if running:
             self.restart()
 
-        self.named_regular.unmask()
-        if named_regular_enabled:
-            self.named_regular.enable()
-
-        if named_regular_running:
-            self.named_regular.start()
+        for svc_name, svc in self.regular_dns_services.items():
+            svc_running = self.restore_state(
+                "{}-regular-running".format(svc_name))
+            svc_enabled = self.restore_state(
+                "{}-regular-enabled".format(svc_name))
+
+            svc.unmask()
+            if svc_enabled:
+                svc.enable()
+            if svc_running:
+                svc.start()
 
         installutils.remove_keytab(self.keytab)
         installutils.remove_ccache(run_as=self.service_user)
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 3e2abefc21..aa040fd34c 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1592,6 +1592,40 @@ def disable_httpd_system_trust(http):
             db.add_cert(cert, nickname, trust_flags)
 
 
+def swap_bind_unit_files(fstore):
+    """
+    IPA changed its unit file, stop named-pkcs11 service using the old and
+    use the new instead
+    """
+    root_logger.info('[Making bind use FreeIPA-specific unit file]')
+
+    if sysupgrade.get_upgrade_state('named-pkcs11.service',
+                                    'ipa_unit_file'):
+        root_logger.info("Already using the IPA-specific unit file")
+        return
+
+    bind_old = services.service('named-pkcs11-regular', api=api)
+    bind = bindinstance.BindInstance(fstore)
+    if bind_old.is_running():
+        try:
+            bind_old.stop()
+        except Exception as e:
+            root_logger.warning('Unable to stop named-pkcs11 service (%s)', e)
+        try:
+            bind.start()
+        except Exception as e:
+            root_logger.warning(
+                'Unable to start ipa-named-pkcs11 service (%s)', e)
+
+    try:
+        bind_old.mask()
+    except Exception as e:
+        root_logger.warning('Unable to mask named service (%s)', e)
+
+    sysupgrade.set_upgrade_state(
+        'named-pkcs11.service', 'ipa_unit_file', True)
+
+
 def upgrade_configuration():
     """
     Execute configuration upgrade of the IPA services
@@ -1756,10 +1790,13 @@ def upgrade_configuration():
 
     # install DNSKeySync service only if DNS is configured on server
     if bindinstance.named_conf_exists():
-            dnskeysyncd = dnskeysyncinstance.DNSKeySyncInstance(fstore)
-            if not dnskeysyncd.is_configured():
-                dnskeysyncd.create_instance(fqdn, api.env.realm)
-                dnskeysyncd.start_dnskeysyncd()
+        # swap the named-pkcs11 systemd unit file for ipa-specific
+        swap_bind_unit_files(fstore)
+
+        dnskeysyncd = dnskeysyncinstance.DNSKeySyncInstance(fstore)
+        if not dnskeysyncd.is_configured():
+            dnskeysyncd.create_instance(fqdn, api.env.realm)
+            dnskeysyncd.start_dnskeysyncd()
 
     cleanup_kdc(fstore)
     cleanup_adtrust(fstore)
diff --git a/ipatests/pytest_plugins/integration/tasks.py b/ipatests/pytest_plugins/integration/tasks.py
index 172f5b8cb3..a13779a207 100644
--- a/ipatests/pytest_plugins/integration/tasks.py
+++ b/ipatests/pytest_plugins/integration/tasks.py
@@ -445,7 +445,7 @@ def install_adtrust(host):
     result = host.run_command(['systemctl', 'is-enabled', 'named'],
                               raiseonerr=False)
     if result.stdout_text.startswith("masked"):
-        host.run_command(['systemctl', 'restart', 'named-pkcs11'])
+        host.run_command(['systemctl', 'restart', 'ipa-named-pkcs11'])
     else:
         host.run_command(['systemctl', 'restart', 'named'])
 
@@ -1249,7 +1249,7 @@ def assert_error(result, stderr_text, returncode=None):
 def restart_named(*args):
     time.sleep(20)  # give a time to DNSSEC daemons to provide keys for named
     for host in args:
-        host.run_command(["systemctl", "restart", "named-pkcs11.service"])
+        host.run_command(["systemctl", "restart", "ipa-named-pkcs11.service"])
     time.sleep(20)  # give a time to named to be ready (zone loading)
 
 
diff --git a/ipatests/test_xmlrpc/test_location_plugin.py b/ipatests/test_xmlrpc/test_location_plugin.py
index a7d8098c9b..2bb9620bc5 100644
--- a/ipatests/test_xmlrpc/test_location_plugin.py
+++ b/ipatests/test_xmlrpc/test_location_plugin.py
@@ -126,9 +126,9 @@ def test_delete_location(self, location):
     not api.Command.dns_is_enabled()['result'], reason='DNS not configured')
 class TestLocationsServer(XMLRPC_test):
     messages = [{
-        u'data': {u'service': u'named-pkcs11.service',
+        u'data': {u'service': u'ipa-named-pkcs11.service',
                   u'server': u'%s' % api.env.host},
-        u'message': (u'Service named-pkcs11.service requires restart '
+        u'message': (u'Service ipa-named-pkcs11.service requires restart '
                      u'on IPA server %s to apply configuration '
                      u'changes.' % api.env.host),
         u'code': 13025,
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to