pgreco / rpms / ipa

Forked from forks/areguera/rpms/ipa 4 years ago
Clone

Blame SOURCES/0066-Delay-enabling-services-until-end-of-installer.patch

2737e7
From f0d829754e2e35225f0dfba980c9f4bae011407e Mon Sep 17 00:00:00 2001
2737e7
From: Christian Heimes <cheimes@redhat.com>
2737e7
Date: Fri, 6 Jul 2018 00:04:39 +0200
2737e7
Subject: [PATCH] Delay enabling services until end of installer
2737e7
2737e7
Service entries in cn=FQDN,cn=masters,cn=ipa,cn=etc are no longer
2737e7
created as enabled. Instead they are flagged as configuredService. At
2737e7
the very end of the installer, the service entries are switched from
2737e7
configured to enabled service.
2737e7
2737e7
- SRV records are created at the very end of the installer.
2737e7
- Dogtag installer only picks fully installed servers
2737e7
- Certmonger ignores all configured but not yet enabled servers.
2737e7
2737e7
Fixes: https://pagure.io/freeipa/issue/7566
2737e7
Signed-off-by: Christian Heimes <cheimes@redhat.com>
2737e7
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
2737e7
Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
2737e7
---
2737e7
 install/tools/ipa-adtrust-install          |  6 +-
2737e7
 install/tools/ipa-ca-install               | 12 ++-
2737e7
 install/tools/ipa-dns-install              |  4 +
2737e7
 ipaserver/dns_data_management.py           | 18 +++--
2737e7
 ipaserver/install/adtrustinstance.py       |  6 +-
2737e7
 ipaserver/install/bindinstance.py          |  6 +-
2737e7
 ipaserver/install/cainstance.py            |  2 +-
2737e7
 ipaserver/install/dnskeysyncinstance.py    |  4 +-
2737e7
 ipaserver/install/httpinstance.py          |  4 +-
2737e7
 ipaserver/install/ipa_kra_install.py       |  7 ++
2737e7
 ipaserver/install/krainstance.py           |  2 +-
2737e7
 ipaserver/install/krbinstance.py           |  4 +-
2737e7
 ipaserver/install/odsexporterinstance.py   |  4 +-
2737e7
 ipaserver/install/opendnssecinstance.py    |  6 +-
2737e7
 ipaserver/install/server/install.py        | 18 +++--
2737e7
 ipaserver/install/server/replicainstall.py |  9 ++-
2737e7
 ipaserver/install/service.py               | 90 ++++++++++++++++++++--
2737e7
 ipaserver/plugins/serverrole.py            |  7 +-
2737e7
 18 files changed, 161 insertions(+), 48 deletions(-)
2737e7
2737e7
diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install
2737e7
index 1484598adba5b1237f00cc55e95167d45a6b40d7..4258f489873b4095a6672e20f2ac5f2858b71982 100755
2737e7
--- a/install/tools/ipa-adtrust-install
2737e7
+++ b/install/tools/ipa-adtrust-install
2737e7
@@ -31,7 +31,7 @@ import six
2737e7
 from optparse import SUPPRESS_HELP  # pylint: disable=deprecated-module
2737e7
 
2737e7
 from ipalib.install import sysrestore
2737e7
-from ipaserver.install import adtrust
2737e7
+from ipaserver.install import adtrust, service
2737e7
 from ipaserver.install.installutils import (
2737e7
     read_password,
2737e7
     check_server_configuration,
2737e7
@@ -210,6 +210,10 @@ def main():
2737e7
     adtrust.install_check(True, options, api)
2737e7
     adtrust.install(True, options, fstore, api)
2737e7
 
2737e7
+    # Enable configured services and update DNS SRV records
2737e7
+    service.enable_services(api.env.host)
2737e7
+    api.Command.dns_update_system_records()
2737e7
+
2737e7
     print("""
2737e7
 =============================================================================
2737e7
 Setup complete
2737e7
diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
2737e7
index a3694007e5815d1c44f642057c749879d336dfc5..215a60ae744577de73a7260bbf3dea5a09a4d118 100755
2737e7
--- a/install/tools/ipa-ca-install
2737e7
+++ b/install/tools/ipa-ca-install
2737e7
@@ -303,18 +303,26 @@ def main():
2737e7
     )
2737e7
     api.finalize()
2737e7
     api.Backend.ldap2.connect()
2737e7
-
2737e7
     domain_level = dsinstance.get_domain_level(api)
2737e7
+
2737e7
     if domain_level > DOMAIN_LEVEL_0:
2737e7
         promote(safe_options, options, filename)
2737e7
     else:
2737e7
         install(safe_options, options, filename)
2737e7
 
2737e7
+    # pki-spawn restarts 389-DS, reconnect
2737e7
+    api.Backend.ldap2.close()
2737e7
+    api.Backend.ldap2.connect()
2737e7
+
2737e7
+    # Enable configured services and update DNS SRV records
2737e7
+    service.enable_services(api.env.host)
2737e7
+    api.Command.dns_update_system_records()
2737e7
+    api.Backend.ldap2.disconnect()
2737e7
+
2737e7
     # execute ipactl to refresh services status
2737e7
     ipautil.run(['ipactl', 'start', '--ignore-service-failures'],
2737e7
                 raiseonerr=False)
2737e7
 
2737e7
-    api.Backend.ldap2.disconnect()
2737e7
 
2737e7
 fail_message = '''
2737e7
 Your system may be partly configured.
2737e7
diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
2737e7
index cb6c5d887f101135ca593ea6d4ed0caf51478a4c..04d1b140d2c79a0fa72d7df47d556643751bddb7 100755
2737e7
--- a/install/tools/ipa-dns-install
2737e7
+++ b/install/tools/ipa-dns-install
2737e7
@@ -36,6 +36,7 @@ from ipapython.config import IPAOptionParser
2737e7
 from ipapython.ipa_log_manager import standard_logging_setup, root_logger
2737e7
 
2737e7
 from ipaserver.install import dns as dns_installer
2737e7
+from ipaserver.install import service
2737e7
 
2737e7
 log_file_name = paths.IPASERVER_INSTALL_LOG
2737e7
 
2737e7
@@ -145,6 +146,9 @@ def main():
2737e7
 
2737e7
     dns_installer.install_check(True, api, False, options, hostname=api.env.host)
2737e7
     dns_installer.install(True, False, options)
2737e7
+    # Enable configured services and update DNS SRV records
2737e7
+    service.enable_services(api.env.host)
2737e7
+    api.Command.dns_update_system_records()
2737e7
 
2737e7
     # execute ipactl to refresh services status
2737e7
     ipautil.run(['ipactl', 'start', '--ignore-service-failures'],
2737e7
diff --git a/ipaserver/dns_data_management.py b/ipaserver/dns_data_management.py
2737e7
index 6016d8a0044d487c3118f43f199b2a433facfa9a..e5987b4bd7b43d3920e9da917258153e448206b7 100644
2737e7
--- a/ipaserver/dns_data_management.py
2737e7
+++ b/ipaserver/dns_data_management.py
2737e7
@@ -65,11 +65,11 @@ class IPASystemRecords(object):
2737e7
     PRIORITY_HIGH = 0
2737e7
     PRIORITY_LOW = 50
2737e7
 
2737e7
-    def __init__(self, api_instance):
2737e7
+    def __init__(self, api_instance, all_servers=False):
2737e7
         self.api_instance = api_instance
2737e7
         self.domain_abs = DNSName(self.api_instance.env.domain).make_absolute()
2737e7
         self.servers_data = {}
2737e7
-        self.__init_data()
2737e7
+        self.__init_data(all_servers=all_servers)
2737e7
 
2737e7
     def reload_data(self):
2737e7
         """
2737e7
@@ -89,14 +89,16 @@ class IPASystemRecords(object):
2737e7
     def __get_location_suffix(self, location):
2737e7
         return location + DNSName('_locations') + self.domain_abs
2737e7
 
2737e7
-    def __init_data(self):
2737e7
+    def __init_data(self, all_servers=False):
2737e7
         self.servers_data = {}
2737e7
 
2737e7
-        servers_result = self.api_instance.Command.server_find(
2737e7
-            no_members=False,
2737e7
-            servrole=u"IPA master",  # only active, fully installed masters
2737e7
-        )['result']
2737e7
-        for s in servers_result:
2737e7
+        kwargs = dict(no_members=False)
2737e7
+        if not all_servers:
2737e7
+            # only active, fully installed masters]
2737e7
+            kwargs["servrole"] = u"IPA master"
2737e7
+        servers = self.api_instance.Command.server_find(**kwargs)
2737e7
+
2737e7
+        for s in servers['result']:
2737e7
             weight, location, roles = self.__get_server_attrs(s)
2737e7
             self.servers_data[s['cn'][0]] = {
2737e7
                 'weight': weight,
2737e7
diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
2737e7
index b4db055045823ce8ae7e3b264e1442a085f81b2d..a7261b92ac227228b5b6af41db621ed2e5e96668 100644
2737e7
--- a/ipaserver/install/adtrustinstance.py
2737e7
+++ b/ipaserver/install/adtrustinstance.py
2737e7
@@ -581,7 +581,7 @@ class ADTRUSTInstance(service.Service):
2737e7
             self.print_msg(err_msg)
2737e7
             self.print_msg("Add the following service records to your DNS " \
2737e7
                            "server for DNS zone %s: " % zone)
2737e7
-            system_records = IPASystemRecords(api)
2737e7
+            system_records = IPASystemRecords(api, all_servers=True)
2737e7
             adtrust_records = system_records.get_base_records(
2737e7
                 [self.fqdn], ["AD trust controller"],
2737e7
                 include_master_role=False, include_kerberos_realm=False)
2737e7
@@ -734,12 +734,12 @@ class ADTRUSTInstance(service.Service):
2737e7
         # Note that self.dm_password is None for ADTrustInstance because
2737e7
         # we ensure to be called as root and using ldapi to use autobind
2737e7
         try:
2737e7
-            self.ldap_enable('ADTRUST', self.fqdn, None, self.suffix)
2737e7
+            self.ldap_configure('ADTRUST', self.fqdn, None, self.suffix)
2737e7
         except (ldap.ALREADY_EXISTS, errors.DuplicateEntry):
2737e7
             root_logger.info("ADTRUST Service startup entry already exists.")
2737e7
 
2737e7
         try:
2737e7
-            self.ldap_enable('EXTID', self.fqdn, None, self.suffix)
2737e7
+            self.ldap_configure('EXTID', self.fqdn, None, self.suffix)
2737e7
         except (ldap.ALREADY_EXISTS, errors.DuplicateEntry):
2737e7
             root_logger.info("EXTID Service startup entry already exists.")
2737e7
 
2737e7
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
2737e7
index 03dce56aa0610b3dc530e6b2a185515be7956e8b..771c6b0483d07b20fbc8470397eed306651f4a8f 100644
2737e7
--- a/ipaserver/install/bindinstance.py
2737e7
+++ b/ipaserver/install/bindinstance.py
2737e7
@@ -664,7 +664,7 @@ class BindInstance(service.Service):
2737e7
         return normalize_zone(self.host_domain) == normalize_zone(self.domain)
2737e7
 
2737e7
     def create_file_with_system_records(self):
2737e7
-        system_records = IPASystemRecords(self.api)
2737e7
+        system_records = IPASystemRecords(self.api, all_servers=True)
2737e7
         text = u'\n'.join(
2737e7
             IPASystemRecords.records_list_from_zone(
2737e7
                 system_records.get_base_records()
2737e7
@@ -741,7 +741,7 @@ class BindInstance(service.Service):
2737e7
         # Instead we reply on the IPA init script to start only enabled
2737e7
         # components as found in our LDAP configuration tree
2737e7
         try:
2737e7
-            self.ldap_enable('DNS', self.fqdn, None, self.suffix)
2737e7
+            self.ldap_configure('DNS', self.fqdn, None, self.suffix)
2737e7
         except errors.DuplicateEntry:
2737e7
             # service already exists (forced DNS reinstall)
2737e7
             # don't crash, just report error
2737e7
@@ -1175,7 +1175,7 @@ class BindInstance(service.Service):
2737e7
             except ValueError as error:
2737e7
                 root_logger.debug(error)
2737e7
 
2737e7
-        # disabled by default, by ldap_enable()
2737e7
+        # disabled by default, by ldap_configure()
2737e7
         if enabled:
2737e7
             self.enable()
2737e7
 
2737e7
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
2737e7
index 0c4d9bf9ad8ae11ac88523857845e16eb62651b9..62e9ad7de6f00eabb48f726a3931eb8acf0ba22b 100644
2737e7
--- a/ipaserver/install/cainstance.py
2737e7
+++ b/ipaserver/install/cainstance.py
2737e7
@@ -1218,7 +1218,7 @@ class CAInstance(DogtagInstance):
2737e7
             config = ['caRenewalMaster']
2737e7
         else:
2737e7
             config = []
2737e7
-        self.ldap_enable('CA', self.fqdn, None, basedn, config)
2737e7
+        self.ldap_configure('CA', self.fqdn, None, basedn, config)
2737e7
 
2737e7
     def setup_lightweight_ca_key_retrieval(self):
2737e7
         if sysupgrade.get_upgrade_state('dogtag', 'setup_lwca_key_retrieval'):
2737e7
diff --git a/ipaserver/install/dnskeysyncinstance.py b/ipaserver/install/dnskeysyncinstance.py
2737e7
index 3849626e5a253667271913337d1a5aa4a72755bb..28468826d7194e7103e61c0ef3957b849e1be896 100644
2737e7
--- a/ipaserver/install/dnskeysyncinstance.py
2737e7
+++ b/ipaserver/install/dnskeysyncinstance.py
2737e7
@@ -384,8 +384,8 @@ class DNSKeySyncInstance(service.Service):
2737e7
 
2737e7
     def __enable(self):
2737e7
         try:
2737e7
-            self.ldap_enable('DNSKeySync', self.fqdn, None,
2737e7
-                             self.suffix, self.extra_config)
2737e7
+            self.ldap_configure('DNSKeySync', self.fqdn, None,
2737e7
+                                self.suffix, self.extra_config)
2737e7
         except errors.DuplicateEntry:
2737e7
             self.logger.error("DNSKeySync service already exists")
2737e7
 
2737e7
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
2737e7
index 7081c7418e76afbd1b4ae28deafefb6b264c62f0..2df51eaa77d3ee3246027a6bcbc4023dbad61160 100644
2737e7
--- a/ipaserver/install/httpinstance.py
2737e7
+++ b/ipaserver/install/httpinstance.py
2737e7
@@ -200,7 +200,7 @@ class HTTPInstance(service.Service):
2737e7
         # We do not let the system start IPA components on its own,
2737e7
         # Instead we reply on the IPA init script to start only enabled
2737e7
         # components as found in our LDAP configuration tree
2737e7
-        self.ldap_enable('HTTP', self.fqdn, None, self.suffix)
2737e7
+        self.ldap_configure('HTTP', self.fqdn, None, self.suffix)
2737e7
 
2737e7
     def configure_selinux_for_httpd(self):
2737e7
         try:
2737e7
@@ -583,7 +583,7 @@ class HTTPInstance(service.Service):
2737e7
         if running:
2737e7
             self.restart()
2737e7
 
2737e7
-        # disabled by default, by ldap_enable()
2737e7
+        # disabled by default, by ldap_configure()
2737e7
         if enabled:
2737e7
             self.enable()
2737e7
 
2737e7
diff --git a/ipaserver/install/ipa_kra_install.py b/ipaserver/install/ipa_kra_install.py
2737e7
index 9ebabe057513141ee76d238a3f20e76a27dd932e..3a639ac20f101293edd7449f8846a451469e2297 100644
2737e7
--- a/ipaserver/install/ipa_kra_install.py
2737e7
+++ b/ipaserver/install/ipa_kra_install.py
2737e7
@@ -224,4 +224,11 @@ class KRAInstaller(KRAInstall):
2737e7
             self.log.error(dedent(self.FAIL_MESSAGE))
2737e7
             raise
2737e7
 
2737e7
+        # pki-spawn restarts 389-DS, reconnect
2737e7
+        api.Backend.ldap2.close()
2737e7
+        api.Backend.ldap2.connect()
2737e7
+
2737e7
+        # Enable configured services and update DNS SRV records
2737e7
+        service.enable_services(api.env.host)
2737e7
+        api.Command.dns_update_system_records()
2737e7
         api.Backend.ldap2.disconnect()
2737e7
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
2737e7
index 915d3c3c6e038eeb6a8f94f1ed7f7008c0ef4ead..a23de3960f0789761b4b86227508236c80e97c2f 100644
2737e7
--- a/ipaserver/install/krainstance.py
2737e7
+++ b/ipaserver/install/krainstance.py
2737e7
@@ -376,4 +376,4 @@ class KRAInstance(DogtagInstance):
2737e7
                 directives[nickname], cert, paths.KRA_CS_CFG_PATH)
2737e7
 
2737e7
     def __enable_instance(self):
2737e7
-        self.ldap_enable('KRA', self.fqdn, None, self.suffix)
2737e7
+        self.ldap_configure('KRA', self.fqdn, None, self.suffix)
2737e7
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
2737e7
index 5971a30fc566f6e96ce0b08632772d33da5602d2..4041d1b5fb3c3cf3db78b6cb282ce5f17793a0e3 100644
2737e7
--- a/ipaserver/install/krbinstance.py
2737e7
+++ b/ipaserver/install/krbinstance.py
2737e7
@@ -240,7 +240,7 @@ class KrbInstance(service.Service):
2737e7
         # We do not let the system start IPA components on its own,
2737e7
         # Instead we reply on the IPA init script to start only enabled
2737e7
         # components as found in our LDAP configuration tree
2737e7
-        self.ldap_enable('KDC', self.fqdn, None, self.suffix)
2737e7
+        self.ldap_configure('KDC', self.fqdn, None, self.suffix)
2737e7
 
2737e7
     def __start_instance(self):
2737e7
         try:
2737e7
@@ -598,7 +598,7 @@ class KrbInstance(service.Service):
2737e7
             except ValueError as error:
2737e7
                 root_logger.debug(error)
2737e7
 
2737e7
-        # disabled by default, by ldap_enable()
2737e7
+        # disabled by default, by ldap_configure()
2737e7
         if enabled:
2737e7
             self.enable()
2737e7
 
2737e7
diff --git a/ipaserver/install/odsexporterinstance.py b/ipaserver/install/odsexporterinstance.py
2737e7
index 59f27f578dab5663b1a7b734dff3699a6996084d..1694704f967b0b2a5debe76252ae859ae8a47f2b 100644
2737e7
--- a/ipaserver/install/odsexporterinstance.py
2737e7
+++ b/ipaserver/install/odsexporterinstance.py
2737e7
@@ -69,8 +69,8 @@ class ODSExporterInstance(service.Service):
2737e7
     def __enable(self):
2737e7
 
2737e7
         try:
2737e7
-            self.ldap_enable('DNSKeyExporter', self.fqdn, None,
2737e7
-                             self.suffix)
2737e7
+            self.ldap_configure('DNSKeyExporter', self.fqdn, None,
2737e7
+                                self.suffix)
2737e7
         except errors.DuplicateEntry:
2737e7
             root_logger.error("DNSKeyExporter service already exists")
2737e7
 
2737e7
diff --git a/ipaserver/install/opendnssecinstance.py b/ipaserver/install/opendnssecinstance.py
2737e7
index bc2974a2cf56e4ade1b778303c14f9ce05a8bf0f..92a46a9f6e318454084398ed625cf27a8250c2af 100644
2737e7
--- a/ipaserver/install/opendnssecinstance.py
2737e7
+++ b/ipaserver/install/opendnssecinstance.py
2737e7
@@ -136,8 +136,8 @@ class OpenDNSSECInstance(service.Service):
2737e7
 
2737e7
     def __enable(self):
2737e7
         try:
2737e7
-            self.ldap_enable('DNSSEC', self.fqdn, None,
2737e7
-                             self.suffix, self.extra_config)
2737e7
+            self.ldap_configure('DNSSEC', self.fqdn, None,
2737e7
+                                self.suffix, self.extra_config)
2737e7
         except errors.DuplicateEntry:
2737e7
             root_logger.error("DNSSEC service already exists")
2737e7
 
2737e7
@@ -368,7 +368,7 @@ class OpenDNSSECInstance(service.Service):
2737e7
 
2737e7
         self.restore_state("kasp_db_configured")  # just eat state
2737e7
 
2737e7
-        # disabled by default, by ldap_enable()
2737e7
+        # disabled by default, by ldap_configure()
2737e7
         if enabled:
2737e7
             self.enable()
2737e7
 
2737e7
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
2737e7
index 3651cde827ecf299e5570feed4936311f91749fb..dcdd9aabb746c4973b3f73934d94225503728f0b 100644
2737e7
--- a/ipaserver/install/server/install.py
2737e7
+++ b/ipaserver/install/server/install.py
2737e7
@@ -869,14 +869,6 @@ def install(installer):
2737e7
 
2737e7
     if options.setup_dns:
2737e7
         dns.install(False, False, options)
2737e7
-    else:
2737e7
-        # Create a BIND instance
2737e7
-        bind = bindinstance.BindInstance(fstore)
2737e7
-        bind.setup(host_name, ip_addresses, realm_name,
2737e7
-                   domain_name, (), 'first', (),
2737e7
-                   zonemgr=options.zonemgr,
2737e7
-                   no_dnssec_validation=options.no_dnssec_validation)
2737e7
-        bind.create_file_with_system_records()
2737e7
 
2737e7
     if options.setup_adtrust:
2737e7
         adtrust.install(False, options, fstore, api)
2737e7
@@ -908,6 +900,16 @@ def install(installer):
2737e7
     # Make sure the files we crated in /var/run are recreated at startup
2737e7
     tasks.configure_tmpfiles()
2737e7
 
2737e7
+    # Enable configured services and update DNS SRV records
2737e7
+    service.enable_services(host_name)
2737e7
+    api.Command.dns_update_system_records()
2737e7
+
2737e7
+    if not options.setup_dns:
2737e7
+        # After DNS and AD trust are configured and services are
2737e7
+        # enabled, create a dummy instance to dump DNS configuration.
2737e7
+        bind = bindinstance.BindInstance(fstore)
2737e7
+        bind.create_file_with_system_records()
2737e7
+
2737e7
     # Everything installed properly, activate ipa service.
2737e7
     services.knownservices.ipa.enable()
2737e7
 
2737e7
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
2737e7
index b10f761e3f643f9fa868451192fa4550b24b6b16..59fec452c674b9941ce731748dd63985a08fefc0 100644
2737e7
--- a/ipaserver/install/server/replicainstall.py
2737e7
+++ b/ipaserver/install/server/replicainstall.py
2737e7
@@ -1518,14 +1518,10 @@ def install(installer):
2737e7
 
2737e7
     if options.setup_dns:
2737e7
         dns.install(False, True, options, api)
2737e7
-    else:
2737e7
-        api.Command.dns_update_system_records()
2737e7
 
2737e7
     if options.setup_adtrust:
2737e7
         adtrust.install(False, options, fstore, api)
2737e7
 
2737e7
-    api.Backend.ldap2.disconnect()
2737e7
-
2737e7
     if not promote:
2737e7
         # Call client install script
2737e7
         service.print_msg("Configuring client side components")
2737e7
@@ -1556,6 +1552,11 @@ def install(installer):
2737e7
     # Make sure the files we crated in /var/run are recreated at startup
2737e7
     tasks.configure_tmpfiles()
2737e7
 
2737e7
+    # Enable configured services and update DNS SRV records
2737e7
+    service.enable_services(config.host_name)
2737e7
+    api.Command.dns_update_system_records()
2737e7
+    api.Backend.ldap2.disconnect()
2737e7
+
2737e7
     # Everything installed properly, activate ipa service.
2737e7
     services.knownservices.ipa.enable()
2737e7
 
2737e7
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
2737e7
index 0523e914aa7debf6aaa82ddcce9b7b26c1833cd3..4271ebe06be03199165894f7a884e17f311896cb 100644
2737e7
--- a/ipaserver/install/service.py
2737e7
+++ b/ipaserver/install/service.py
2737e7
@@ -24,6 +24,7 @@ import socket
2737e7
 import datetime
2737e7
 import traceback
2737e7
 import tempfile
2737e7
+import warnings
2737e7
 
2737e7
 import six
2737e7
 
2737e7
@@ -59,6 +60,10 @@ SERVICE_LIST = {
2737e7
     'DNSKeySync': ('ipa-dnskeysyncd', 110),
2737e7
 }
2737e7
 
2737e7
+CONFIGURED_SERVICE = u'configuredService'
2737e7
+ENABLED_SERVICE = 'enabledService'
2737e7
+
2737e7
+
2737e7
 def print_msg(message, output_fd=sys.stdout):
2737e7
     root_logger.debug(message)
2737e7
     output_fd.write(message)
2737e7
@@ -120,7 +125,7 @@ def find_providing_server(svcname, conn, host_name=None, api=api):
2737e7
     """
2737e7
     dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
2737e7
     query_filter = conn.make_filter({'objectClass': 'ipaConfigObject',
2737e7
-                                     'ipaConfigString': 'enabledService',
2737e7
+                                     'ipaConfigString': ENABLED_SERVICE,
2737e7
                                      'cn': svcname}, rules='&')
2737e7
     try:
2737e7
         entries, _trunc = conn.find_entries(filter=query_filter, base_dn=dn)
2737e7
@@ -217,6 +222,53 @@ def set_service_entry_config(name, fqdn, config_values,
2737e7
         raise e
2737e7
 
2737e7
 
2737e7
+def enable_services(fqdn):
2737e7
+    """Change all configured services to enabled
2737e7
+
2737e7
+    Server.ldap_configure() only marks a service as configured. Services
2737e7
+    are enabled at the very end of installation.
2737e7
+
2737e7
+    Note: DNS records must be updated with dns_update_system_records, too.
2737e7
+
2737e7
+    :param fqdn: hostname of server
2737e7
+    """
2737e7
+    ldap2 = api.Backend.ldap2
2737e7
+    search_base = DN(('cn', fqdn), api.env.container_masters, api.env.basedn)
2737e7
+    search_filter = ldap2.make_filter(
2737e7
+        {
2737e7
+            'objectClass': 'ipaConfigObject',
2737e7
+            'ipaConfigString': CONFIGURED_SERVICE
2737e7
+        },
2737e7
+        rules='&'
2737e7
+    )
2737e7
+    entries = ldap2.get_entries(
2737e7
+        search_base,
2737e7
+        filter=search_filter,
2737e7
+        scope=api.Backend.ldap2.SCOPE_ONELEVEL,
2737e7
+        attrs_list=['cn', 'ipaConfigString']
2737e7
+    )
2737e7
+    for entry in entries:
2737e7
+        name = entry['cn']
2737e7
+        cfgstrings = entry.setdefault('ipaConfigString', [])
2737e7
+        for value in list(cfgstrings):
2737e7
+            if value.lower() == CONFIGURED_SERVICE.lower():
2737e7
+                cfgstrings.remove(value)
2737e7
+        if not case_insensitive_attr_has_value(cfgstrings, ENABLED_SERVICE):
2737e7
+            cfgstrings.append(ENABLED_SERVICE)
2737e7
+
2737e7
+        try:
2737e7
+            ldap2.update_entry(entry)
2737e7
+        except errors.EmptyModlist:
2737e7
+            root_logger.debug("Nothing to do for service %s", name)
2737e7
+        except Exception:
2737e7
+            root_logger.exception(
2737e7
+                "failed to set service %s config values", name
2737e7
+            )
2737e7
+            raise
2737e7
+        else:
2737e7
+            root_logger.debug("Enabled service %s for %s", name, fqdn)
2737e7
+
2737e7
+
2737e7
 class Service(object):
2737e7
     def __init__(self, service_name, service_desc=None, sstore=None,
2737e7
                  fstore=None, api=api, realm_name=None,
2737e7
@@ -522,7 +574,35 @@ class Service(object):
2737e7
         self.steps = []
2737e7
 
2737e7
     def ldap_enable(self, name, fqdn, dm_password=None, ldap_suffix='',
2737e7
-                    config=[]):
2737e7
+                    config=()):
2737e7
+        """Legacy function, all services should use ldap_configure()
2737e7
+        """
2737e7
+        warnings.warn(
2737e7
+            "ldap_enable is deprecated, use ldap_configure instead.",
2737e7
+            DeprecationWarning,
2737e7
+            stacklevel=2
2737e7
+        )
2737e7
+        self._ldap_enable(ENABLED_SERVICE, name, fqdn, ldap_suffix, config)
2737e7
+
2737e7
+    def ldap_configure(self, name, fqdn, dm_password=None, ldap_suffix='',
2737e7
+                       config=()):
2737e7
+        """Create or modify service entry in cn=masters,cn=ipa,cn=etc
2737e7
+
2737e7
+        Contrary to ldap_enable(), the method only sets
2737e7
+        ipaConfigString=configuredService. ipaConfigString=enabledService
2737e7
+        is set at the very end of the installation process, to ensure that
2737e7
+        other machines see this master/replica after it is fully installed.
2737e7
+
2737e7
+        To switch all configured services to enabled, use::
2737e7
+
2737e7
+            ipaserver.install.service.enable_services(api.env.host)
2737e7
+            api.Command.dns_update_system_records()
2737e7
+        """
2737e7
+        self._ldap_enable(
2737e7
+            CONFIGURED_SERVICE, name, fqdn, ldap_suffix, config
2737e7
+        )
2737e7
+
2737e7
+    def _ldap_enable(self, value, name, fqdn, ldap_suffix, config):
2737e7
         extra_config_opts = [
2737e7
             ' '.join([u'startOrder', unicode(SERVICE_LIST[name][1])])
2737e7
         ]
2737e7
@@ -533,7 +613,7 @@ class Service(object):
2737e7
         set_service_entry_config(
2737e7
             name,
2737e7
             fqdn,
2737e7
-            [u'enabledService'],
2737e7
+            [value],
2737e7
             ldap_suffix=ldap_suffix,
2737e7
             post_add_config=extra_config_opts)
2737e7
 
2737e7
@@ -559,7 +639,7 @@ class Service(object):
2737e7
 
2737e7
         # case insensitive
2737e7
         for value in entry.get('ipaConfigString', []):
2737e7
-            if value.lower() == u'enabledservice':
2737e7
+            if value.lower() == ENABLED_SERVICE:
2737e7
                 entry['ipaConfigString'].remove(value)
2737e7
                 break
2737e7
 
2737e7
@@ -672,7 +752,7 @@ class SimpleServiceInstance(Service):
2737e7
         if self.gensvc_name == None:
2737e7
             self.enable()
2737e7
         else:
2737e7
-            self.ldap_enable(self.gensvc_name, self.fqdn, None, self.suffix)
2737e7
+            self.ldap_configure(self.gensvc_name, self.fqdn, None, self.suffix)
2737e7
 
2737e7
     def is_installed(self):
2737e7
         return self.service.is_installed()
2737e7
diff --git a/ipaserver/plugins/serverrole.py b/ipaserver/plugins/serverrole.py
2737e7
index db88b3885c538c2800f6e4a1d649083859d43641..35b199387b4d3512d39f197d125c20571e23ad7a 100644
2737e7
--- a/ipaserver/plugins/serverrole.py
2737e7
+++ b/ipaserver/plugins/serverrole.py
2737e7
@@ -15,16 +15,21 @@ IPA server roles
2737e7
 """) + _("""
2737e7
 Get status of roles (DNS server, CA, etc.) provided by IPA masters.
2737e7
 """) + _("""
2737e7
+The status of a role is either enabled, configured, or absent.
2737e7
+""") + _("""
2737e7
 EXAMPLES:
2737e7
 """) + _("""
2737e7
   Show status of 'DNS server' role on a server:
2737e7
     ipa server-role-show ipa.example.com "DNS server"
2737e7
 """) + _("""
2737e7
   Show status of all roles containing 'AD' on a server:
2737e7
-    ipa server-role-find --server ipa.example.com --role='AD'
2737e7
+    ipa server-role-find --server ipa.example.com --role="AD trust controller"
2737e7
 """) + _("""
2737e7
   Show status of all configured roles on a server:
2737e7
     ipa server-role-find ipa.example.com
2737e7
+""") + _("""
2737e7
+  Show implicit IPA master role:
2737e7
+    ipa server-role-find --include-master
2737e7
 """)
2737e7
 
2737e7
 
2737e7
-- 
2737e7
2.17.1
2737e7