URL: https://github.com/freeipa/freeipa/pull/5522 Author: flo-renaud Title: #5522: [Backport][ipa-4-9] Ensure IPA is running (ideally) before uninstalling the KRA Action: opened
PR body: """ This PR was opened automatically because PR #5485 was pushed to master and backport to ipa-4-9 is required. """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/5522/head:pr5522 git checkout pr5522
From 0e800dfedab7e6e87fbc43588097082b144849ab Mon Sep 17 00:00:00 2001 From: Rob Crittenden <[email protected]> Date: Fri, 22 Jan 2021 17:23:53 -0500 Subject: [PATCH 1/6] Change CA profile migration message from info to debug This is an informational message and clutters the installation screen with no end-user benefit. Logging it as debug is sufficient to know what is going on. --- ipaserver/install/cainstance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 131418df7b0..8196e3dee1e 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -1959,7 +1959,7 @@ def import_included_profiles(): _create_dogtag_profile(profile_id, profile_data, overwrite=True) logger.debug("Imported profile '%s'", profile_id) else: - logger.info( + logger.debug( "Profile '%s' is already in LDAP; skipping", profile_id ) @@ -2034,7 +2034,7 @@ def migrate_profiles_to_ldap(): state = profile_states.get(profile_id.lower(), ProfileState.MISSING) if state != ProfileState.MISSING: # We don't reconsile enabled/disabled state. - logger.info( + logger.debug( "Profile '%s' is already in LDAP and %s; skipping", profile_id, state.value ) From 8b2ade98eeb8e8ea2c9c9488a0a5ea3f722de76b Mon Sep 17 00:00:00 2001 From: Rob Crittenden <[email protected]> Date: Fri, 22 Jan 2021 17:25:28 -0500 Subject: [PATCH 2/6] Use the new API introduced in PKI 10.8 https://www.dogtagpki.org/wiki/PKI_10.8_Python_Changes --- ipaserver/install/dogtaginstance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py index 52dfc016a1e..7f2a4a32e41 100644 --- a/ipaserver/install/dogtaginstance.py +++ b/ipaserver/install/dogtaginstance.py @@ -84,7 +84,7 @@ def get_security_domain(): cert_paths=paths.IPA_CA_CRT ) domain_client = pki.system.SecurityDomainClient(connection) - info = domain_client.get_security_domain_info() + info = domain_client.get_domain_info() return info @@ -97,7 +97,7 @@ def is_installing_replica(sys_type): """ info = get_security_domain() try: - sys_list = info.systems[sys_type] + sys_list = info.subsystems[sys_type] return len(sys_list.hosts) > 0 except KeyError: return False From a5be7127153b622da7660bf7353d059dfd3a0fc8 Mon Sep 17 00:00:00 2001 From: Rob Crittenden <[email protected]> Date: Tue, 26 Jan 2021 10:12:31 -0500 Subject: [PATCH 3/6] ipactl: support script status 3, program is not running Return status 3 if ipactl status can't start 389-ds or if any of the expected services is not running. https://pagure.io/freeipa/issue/8588 Signed-off-by: Rob Crittenden <[email protected]> --- ipaserver/install/ipactl.py | 41 ++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/ipaserver/install/ipactl.py b/ipaserver/install/ipactl.py index f813d0d728c..545a4843e3a 100644 --- a/ipaserver/install/ipactl.py +++ b/ipaserver/install/ipactl.py @@ -613,6 +613,22 @@ def ipa_restart(options): def ipa_status(options): + """Report status of IPA-owned processes + + The LSB defines the possible status values as: + + 0 program is running or service is OK + 1 program is dead and /var/run pid file exists + 2 program is dead and /var/lock lock file exists + 3 program is not running + 4 program or service status is unknown + 5-99 reserved for future LSB use + 100-149 reserved for distribution use + 150-199 reserved for application use + 200-254 reserved + + We only really care about 0, 3 and 4. + """ try: dirsrv = services.knownservices.dirsrv @@ -627,7 +643,8 @@ def ipa_status(options): svc_list = [] except Exception as e: raise IpactlError( - "Failed to get list of services to probe status: " + str(e) + "Failed to get list of services to probe status: " + str(e), + 4 ) dirsrv = services.knownservices.dirsrv @@ -636,19 +653,19 @@ def ipa_status(options): print("Directory Service: RUNNING") else: print("Directory Service: STOPPED") - if len(svc_list) == 0: - print( - ( - "Directory Service must be running in order to " - "obtain status of other services" - ) - ) except Exception as e: - raise IpactlError("Failed to get Directory Service status") + raise IpactlError("Failed to get Directory Service status", 4) if len(svc_list) == 0: - return + raise IpactlError( + ( + "Directory Service must be running in order to " + "obtain status of other services" + ), + 3, + ) + stopped = 0 for svc in svc_list: svchandle = services.service(svc, api=api) try: @@ -656,9 +673,13 @@ def ipa_status(options): print("%s Service: RUNNING" % svc) else: print("%s Service: STOPPED" % svc) + stopped += 1 except Exception: emit_err("Failed to get %s Service status" % svc) + if stopped > 0: + raise IpactlError("%d service(s) are not running" % stopped, 3) + def main(): if not os.getegid() == 0: From 77feac91a0fb62fa4ccbb9743bf81346e23d9946 Mon Sep 17 00:00:00 2001 From: Rob Crittenden <[email protected]> Date: Mon, 25 Jan 2021 11:40:22 -0500 Subject: [PATCH 4/6] Ensure IPA is running (ideally) before uninstalling the KRA The KRA attempts to unregister itself from the security domain which requires that IPA be running for this to succeed. 1. Move the KRA uninstall call prior to stopping all IPA services 2. Try to start IPA if it isn't running and a KRA is configured It isn't mandatory that IPA be running for the KRA uninstall to succeed but it will suppress a pretty scary backtrace and error message. https://pagure.io/freeipa/issue/8550 Signed-off-by: Rob Crittenden <[email protected]> --- ipaserver/install/ipactl.py | 23 ++++++++++++++++------- ipaserver/install/kra.py | 19 +++++++++++++++++++ ipaserver/install/server/install.py | 8 ++++++-- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/ipaserver/install/ipactl.py b/ipaserver/install/ipactl.py index 545a4843e3a..7f0361d3741 100644 --- a/ipaserver/install/ipactl.py +++ b/ipaserver/install/ipactl.py @@ -306,7 +306,12 @@ def get_config(dirsrv): return deduplicate(ordered_list) -def get_config_from_file(): +def get_config_from_file(rval): + """ + Get the list of configured services from the cached file. + + :param rval: The return value for any exception that is raised. + """ svc_list = [] @@ -316,7 +321,8 @@ def get_config_from_file(): except Exception as e: raise IpactlError( "Unknown error when retrieving list of services from file: %s" - % str(e) + % str(e), + 4 ) # the framework can start/stop a number of related services we are not @@ -427,7 +433,7 @@ def ipa_start(options): def ipa_stop(options): dirsrv = services.knownservices.dirsrv try: - svc_list = get_config_from_file() + svc_list = get_config_from_file(rval=4) except Exception as e: # Issue reading the file ? Let's try to get data from LDAP as a # fallback @@ -509,7 +515,7 @@ def ipa_restart(options): old_svc_list = [] try: - old_svc_list = get_config_from_file() + old_svc_list = get_config_from_file(rval=4) except Exception as e: emit_err("Failed to get service list from file: " + str(e)) # fallback to what's in LDAP @@ -629,13 +635,14 @@ def ipa_status(options): We only really care about 0, 3 and 4. """ + socket_activated = ('ipa-ods-exporter', 'ipa-otpd',) try: dirsrv = services.knownservices.dirsrv if dirsrv.is_running(): svc_list = get_config(dirsrv) else: - svc_list = get_config_from_file() + svc_list = get_config_from_file(rval=1) except IpactlError as e: if os.path.exists(tasks.get_svc_list_file()): raise e @@ -647,12 +654,14 @@ def ipa_status(options): 4 ) + stopped = 0 dirsrv = services.knownservices.dirsrv try: if dirsrv.is_running(): print("Directory Service: RUNNING") else: print("Directory Service: STOPPED") + stopped = 1 except Exception as e: raise IpactlError("Failed to get Directory Service status", 4) @@ -665,7 +674,6 @@ def ipa_status(options): 3, ) - stopped = 0 for svc in svc_list: svchandle = services.service(svc, api=api) try: @@ -673,7 +681,8 @@ def ipa_status(options): print("%s Service: RUNNING" % svc) else: print("%s Service: STOPPED" % svc) - stopped += 1 + if svc not in socket_activated: + stopped += 1 except Exception: emit_err("Failed to get %s Service status" % svc) diff --git a/ipaserver/install/kra.py b/ipaserver/install/kra.py index c7a097b58d0..ffed5df1402 100644 --- a/ipaserver/install/kra.py +++ b/ipaserver/install/kra.py @@ -8,6 +8,7 @@ from __future__ import absolute_import +import logging import os from ipalib import api @@ -23,6 +24,8 @@ from . import dogtag +logger = logging.getLogger(__name__) + def install_check(api, replica_config, options): if replica_config is not None and not replica_config.setup_kra: @@ -113,6 +116,22 @@ def install(api, replica_config, options, custodia): named.restart(capture_output=True) +def uninstall_check(options): + """IPA needs to be running so pkidestroy can unregister KRA""" + kra = krainstance.KRAInstance(api.env.realm) + if not kra.is_installed(): + return + + result = ipautil.run([paths.IPACTL, 'status'], + raiseonerr=False) + + if result.returncode not in [0, 4]: + try: + ipautil.run([paths.IPACTL, 'start']) + except Exception: + logger.info("Re-starting IPA failed, continuing uninstall") + + def uninstall(): kra = krainstance.KRAInstance(api.env.realm) kra.stop_tracking_certificates() diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index c0d33f3e71f..bc77f8a689b 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -1098,6 +1098,8 @@ def uninstall_check(installer): "uninstall procedure?", False): raise ScriptError("Aborting uninstall operation.") + kra.uninstall_check(options) + try: api.Backend.ldap2.connect(autobind=True) @@ -1165,6 +1167,10 @@ def uninstall(installer): rv = 0 + # Uninstall the KRA prior to shutting the services down so it + # can un-register with the CA. + kra.uninstall() + print("Shutting down all IPA services") try: services.knownservices.ipa.stop() @@ -1177,8 +1183,6 @@ def uninstall(installer): restore_time_sync(sstore, fstore) - kra.uninstall() - ca.uninstall() dns.uninstall() From bdaf0a915829b7b8b41e586056bdd4ad46007838 Mon Sep 17 00:00:00 2001 From: Rob Crittenden <[email protected]> Date: Tue, 26 Jan 2021 16:27:57 -0500 Subject: [PATCH 5/6] Add exit status to the ipactl man page The existing return codes were undocumented but basically followed the LSB. Document those along with the new options for status. https://pagure.io/freeipa/issue/8550 Signed-off-by: Rob Crittenden <[email protected]> --- install/tools/man/ipactl.8 | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/install/tools/man/ipactl.8 b/install/tools/man/ipactl.8 index fb533aae200..df7baf585b5 100644 --- a/install/tools/man/ipactl.8 +++ b/install/tools/man/ipactl.8 @@ -52,3 +52,30 @@ If any service start fails, do not rollback the services, continue with the oper .TP \fB\-f\fR, \fB\-\-force\fR Force IPA to start. Combine options --skip-version-check and --ignore-service-failures +.SH "EXIT STATUS" + +All actions except status: + +0 success + +1 a generic error occurred + +2 unknown or invalid argument(s) + +4 user has insufficient privilege + +6 IPA server is not configured + +For the status action: + +0 service is running + +3 service is not running + +4 service status is unknown (or unconfigured) + +If not executed as root then the status action will return 4 for +insufficient privileges. + +Some services are socket activated and may show as STOPPED by the status +action. These services include ipa-ods-exporter and ipa-otpd. From d91d53ceb6cc65bb804c64aa4c84a640d8ff84fb Mon Sep 17 00:00:00 2001 From: Rob Crittenden <[email protected]> Date: Wed, 27 Jan 2021 16:35:22 -0500 Subject: [PATCH 6/6] ipatests: Handle non-zero return code in test_ipactl_scenario_check https://pagure.io/freeipa/issue/8550 Signed-off-by: Rob Crittenden <[email protected]> --- ipatests/test_integration/test_installation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py index 4cc0f21921c..fca8860d9b9 100644 --- a/ipatests/test_integration/test_installation.py +++ b/ipatests/test_integration/test_installation.py @@ -766,7 +766,8 @@ def test_ipactl_scenario_check(self): service_start = [ svcs for svcs in ipa_services_name if svcs not in service_stop ] - cmd = self.master.run_command(['ipactl', 'status']) + cmd = self.master.run_command(['ipactl', 'status'], raiseonerr=False) + assert cmd.returncode == 3 for service in service_start: assert f"{service} Service: RUNNING" in cmd.stdout_text for service in service_stop:
_______________________________________________ FreeIPA-devel mailing list -- [email protected] To unsubscribe send an email to [email protected] Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/[email protected]
