pgreco / rpms / ipa

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

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

95ea96
From 4caf0c14ad38a1dae494489b13f4109cdb3ba340 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
---
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 +-
95ea96
 ipaserver/install/bindinstance.py          |  8 +-
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 +++--
95ea96
 ipaserver/install/server/replicainstall.py |  8 +-
95ea96
 ipaserver/install/service.py               | 88 ++++++++++++++++++++--
2737e7
 ipaserver/plugins/serverrole.py            |  7 +-
95ea96
 18 files changed, 161 insertions(+), 47 deletions(-)
2737e7
2737e7
diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install
95ea96
index d4e5d4c09cf6b7c1521bcecb79bb6fd7235fc799..a870d136e242affe6627cd4c44a173a80a9ab1c6 100755
2737e7
--- a/install/tools/ipa-adtrust-install
2737e7
+++ b/install/tools/ipa-adtrust-install
95ea96
@@ -32,7 +32,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,
95ea96
@@ -212,6 +212,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
95ea96
index e4e24fb8c5261e77dd9d3e89cbe42dba519b932e..f78f43d94981d29939a247f3c492c5e7340298ea 100755
2737e7
--- a/install/tools/ipa-ca-install
2737e7
+++ b/install/tools/ipa-ca-install
95ea96
@@ -332,18 +332,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
95ea96
index a7f136b16ab4871518f5fd776d49e55c2364c54e..57dde5a5da4fad162c93e9e0416b54961de4c1e3 100755
2737e7
--- a/install/tools/ipa-dns-install
2737e7
+++ b/install/tools/ipa-dns-install
95ea96
@@ -37,6 +37,7 @@ from ipapython.config import IPAOptionParser
95ea96
 from ipapython.ipa_log_manager import standard_logging_setup
2737e7
 
2737e7
 from ipaserver.install import dns as dns_installer
2737e7
+from ipaserver.install import service
2737e7
 
95ea96
 logger = logging.getLogger(os.path.basename(__file__))
2737e7
 
95ea96
@@ -148,6 +149,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
95ea96
index 675dd481b461aa14d8adf8393a2168ac84ecac86..673397ef2b2252f431eec1f3e1f71dc45ff87511 100644
2737e7
--- a/ipaserver/dns_data_management.py
2737e7
+++ b/ipaserver/dns_data_management.py
95ea96
@@ -68,11 +68,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
         """
95ea96
@@ -92,14 +92,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
95ea96
index a075801ebec20ea8277445e0bac788c06e0b0a91..2da46d67495014fb38e5ee8c6a98ede93ef8762d 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)
95ea96
@@ -736,12 +736,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):
95ea96
             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):
95ea96
             logger.info("EXTID Service startup entry already exists.")
2737e7
 
2737e7
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
95ea96
index 203a6405f815d47c0dc33977e77012a2c85916ff..7c858aab4417ccf3a4999fcaaa1c7e0f93464e4d 100644
2737e7
--- a/ipaserver/install/bindinstance.py
2737e7
+++ b/ipaserver/install/bindinstance.py
95ea96
@@ -669,7 +669,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()
95ea96
@@ -746,7 +746,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
95ea96
@@ -1180,7 +1180,9 @@ class BindInstance(service.Service):
2737e7
             except ValueError as error:
95ea96
                 logger.debug('%s', error)
2737e7
 
2737e7
-        # disabled by default, by ldap_enable()
95ea96
+        installutils.rmtree(paths.BIND_LDAP_DNS_IPA_WORKDIR)
95ea96
+
2737e7
+        # disabled by default, by ldap_configure()
2737e7
         if enabled:
2737e7
             self.enable()
95ea96
         else:
2737e7
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
95ea96
index b58fbb4c881d247d6b5fb661f4085ec82c3cc811..51fdbe9c61e06ab9d72d78aee8786f9bceca137b 100644
2737e7
--- a/ipaserver/install/cainstance.py
2737e7
+++ b/ipaserver/install/cainstance.py
95ea96
@@ -1258,7 +1258,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
95ea96
index b865ee8aa79c17502a3784878f8f6f45d05213a6..2e773f3adae8130f578e6f3fbfe8c3a414d523cb 100644
2737e7
--- a/ipaserver/install/dnskeysyncinstance.py
2737e7
+++ b/ipaserver/install/dnskeysyncinstance.py
95ea96
@@ -382,8 +382,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:
95ea96
             logger.error("DNSKeySync service already exists")
2737e7
 
2737e7
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
95ea96
index bdd79b1dafda7de664eed664a18bf36c541212bc..0b7023c2f1b0feb996e0dd0adbefbd49c51da757 100644
2737e7
--- a/ipaserver/install/httpinstance.py
2737e7
+++ b/ipaserver/install/httpinstance.py
95ea96
@@ -196,7 +196,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:
95ea96
@@ -609,7 +609,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
95ea96
index 07e11ea69ded8832015dd69ea43ff338c5f9df95..b536685f5f1f3fccab07fd37aa001958e2d38420 100644
2737e7
--- a/ipaserver/install/ipa_kra_install.py
2737e7
+++ b/ipaserver/install/ipa_kra_install.py
95ea96
@@ -227,4 +227,11 @@ class KRAInstaller(KRAInstall):
95ea96
             logger.error('%s', 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
95ea96
index 9483f0ec4edbabea0f7eff0dd5dd223377653536..c1daa2869b7cba79e29d2db61c090c145304397f 100644
2737e7
--- a/ipaserver/install/krainstance.py
2737e7
+++ b/ipaserver/install/krainstance.py
95ea96
@@ -392,4 +392,4 @@ class KRAInstance(DogtagInstance):
95ea96
                 directives[nickname], cert)
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
95ea96
index a356d5e0c1b96dc6511c335fc22a326a2133bdd8..33d66fb94b0a1f7571b22120e5159a0e0ad2e675 100644
2737e7
--- a/ipaserver/install/krbinstance.py
2737e7
+++ b/ipaserver/install/krbinstance.py
95ea96
@@ -242,7 +242,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:
95ea96
@@ -607,7 +607,7 @@ class KrbInstance(service.Service):
2737e7
             except ValueError as error:
95ea96
                 logger.debug("%s", 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
95ea96
index b301a167f80d171c0dd0e6282a6021fcbdca8f9e..4856f5642d8e2c4c9e9089cd44a85e759c4c6ca0 100644
2737e7
--- a/ipaserver/install/odsexporterinstance.py
2737e7
+++ b/ipaserver/install/odsexporterinstance.py
95ea96
@@ -73,8 +73,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:
95ea96
             logger.error("DNSKeyExporter service already exists")
2737e7
 
2737e7
diff --git a/ipaserver/install/opendnssecinstance.py b/ipaserver/install/opendnssecinstance.py
95ea96
index d608294cbbab9179d95b2333323f5d378940a936..0337bb22fea44f95ee9077423136353a991325db 100644
2737e7
--- a/ipaserver/install/opendnssecinstance.py
2737e7
+++ b/ipaserver/install/opendnssecinstance.py
95ea96
@@ -140,8 +140,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:
95ea96
             logger.error("DNSSEC service already exists")
2737e7
 
95ea96
@@ -372,7 +372,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
95ea96
index e96ae97c74ee1598683d1ef3f2570e8de93c9943..a341408f78f24055d807ae49c8a0cda81bfb3ec4 100644
2737e7
--- a/ipaserver/install/server/install.py
2737e7
+++ b/ipaserver/install/server/install.py
95ea96
@@ -870,14 +870,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)
95ea96
@@ -906,6 +898,16 @@ def install(installer):
95ea96
     except Exception:
95ea96
         raise ScriptError("Configuration of client side components failed!")
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
95ea96
index 33f3ae9e616b34a3ab0ff8e4257552855e817e7c..0bf3568a300a133fa505dc8fc339c6677f9c5f73 100644
2737e7
--- a/ipaserver/install/server/replicainstall.py
2737e7
+++ b/ipaserver/install/server/replicainstall.py
95ea96
@@ -1520,14 +1520,11 @@ 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
 
95ea96
     ca_servers = service.find_providing_servers('CA', api.Backend.ldap2, api)
2737e7
-    api.Backend.ldap2.disconnect()
95ea96
 
2737e7
     if not promote:
2737e7
         # Call client install script
95ea96
@@ -1556,6 +1553,11 @@ def install(installer):
95ea96
         # remove the extracted replica file
95ea96
         remove_replica_info_dir(installer)
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
95ea96
index 4c320de9d64676373cd41ff839889f2448a19a46..0106379ea38e4a3fef8436256d6f315f524b8dee 100644
2737e7
--- a/ipaserver/install/service.py
2737e7
+++ b/ipaserver/install/service.py
95ea96
@@ -27,6 +27,7 @@ import socket
2737e7
 import datetime
2737e7
 import traceback
2737e7
 import tempfile
2737e7
+import warnings
2737e7
 
2737e7
 import six
2737e7
 
95ea96
@@ -62,6 +63,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):
95ea96
     logger.debug("%s", message)
2737e7
     output_fd.write(message)
95ea96
@@ -123,7 +128,7 @@ def find_providing_servers(svcname, conn, 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)
95ea96
@@ -232,6 +237,51 @@ 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:
95ea96
+            logger.debug("Nothing to do for service %s", name)
2737e7
+        except Exception:
95ea96
+            logger.exception("failed to set service %s config values", name)
2737e7
+            raise
2737e7
+        else:
95ea96
+            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,
95ea96
@@ -538,7 +588,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
         ]
95ea96
@@ -549,7 +627,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
 
95ea96
@@ -575,7 +653,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
 
95ea96
@@ -688,7 +766,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
95ea96
index 5b7ccfb342d0a54bfd6f2cdc53c7d31201ed5989..199978000ce8cf783bda50c46b7c9fa109f70ad6 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