From: Simo Sorce <sso...@redhat.com> We check (possibly different) data from LDAP only at (re)start. This way we always shutdown exactly the services we started even if the list changed in the meanwhile (we avoid leaving a service running even if it was removed from LDAP as the admin decided it should not be started in future).
This should also fix a problematic deadlock with systemd when we try to read the list of service from LDAP at shutdown. --- freeipa.spec.in | 2 + init/systemd/ipa.conf.tmpfiles | 1 + install/tools/ipactl | 199 ++++++++++++++++++++++++++++------------ 3 files changed, 143 insertions(+), 59 deletions(-) diff --git a/freeipa.spec.in b/freeipa.spec.in index af76118fd0294fa4d8934b747c254b891ae7f2cb..397d60b1d2a22b1d1eb26b8f567f381da526f282 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -447,6 +447,7 @@ install -m 0644 init/systemd/ipa.conf.tmpfiles %{buildroot}%{_sysconfdir}/tmpfil mkdir -p %{buildroot}%{_localstatedir}/run/ install -d -m 0700 %{buildroot}%{_localstatedir}/run/ipa_memcached/ +install -d -m 0700 %{buildroot}%{_localstatedir}/run/ipa/ mkdir -p %{buildroot}%{_libdir}/krb5/plugins/libkrb5 touch %{buildroot}%{_libdir}/krb5/plugins/libkrb5/winbind_krb5_locator.so @@ -624,6 +625,7 @@ fi %{_sysconfdir}/cron.d/ipa-compliance %config(noreplace) %{_sysconfdir}/sysconfig/ipa_memcached %dir %attr(0700,apache,apache) %{_localstatedir}/run/ipa_memcached/ +%dir %attr(0700,root,root) %{_localstatedir}/run/ipa/ %if 0%{?fedora} >= 15 %config %{_sysconfdir}/tmpfiles.d/ipa.conf %endif diff --git a/init/systemd/ipa.conf.tmpfiles b/init/systemd/ipa.conf.tmpfiles index e4b679a55d68a6b83991ac72dd520c32b2a0de50..1e7a896ed8df00c97f2d092504e2a65960bb341d 100644 --- a/init/systemd/ipa.conf.tmpfiles +++ b/init/systemd/ipa.conf.tmpfiles @@ -1 +1,2 @@ d /var/run/ipa_memcached 0700 apache apache +d /var/run/ipa 0700 root root diff --git a/install/tools/ipactl b/install/tools/ipactl index d4b2c0878f2b62fd12198f76bef01ef70e9f3de1..9b151ab9f9bd10423d5145a1fcf028b6ddb65096 100755 --- a/install/tools/ipactl +++ b/install/tools/ipactl @@ -34,6 +34,7 @@ try: import ldap.sasl import ldapurl import socket + import json except ImportError: print >> sys.stderr, """\ There was a problem importing one of the required Python modules. The @@ -162,11 +163,30 @@ def get_config(dirsrv): for p in entry[1]['ipaConfigString']: if p.startswith('startOrder '): order = p.split()[1] - svc_list.append((order, name)) + svc_list.append([order, name]) + + ordered_list = [] + for (order, svc) in sorted(svc_list): + ordered_list.append(service.SERVICE_LIST[svc][0]) + return ordered_list + +def get_config_from_file(): + + svc_list = [] + + try: + f = open(ipaservices.get_svc_list_file(), 'r') + svc_list = json.load(f) + except Exception, e: + raise IpactlError("Unknown error when retrieving list of services from file: " + str(e)) return svc_list def ipa_start(options): + + if os.path.isfile(ipaservices.get_svc_list_file()): + raise IpactlError("IPA service already started!") + dirsrv = ipaservices.knownservices.dirsrv try: print "Starting Directory Service" @@ -174,7 +194,7 @@ def ipa_start(options): except Exception, e: raise IpactlError("Failed to start Directory Service: " + str(e)) - svc_list = [] + ldap_list = [] try: svc_list = get_config(dirsrv) except Exception, e: @@ -191,21 +211,19 @@ def ipa_start(options): raise IpactlError() if len(svc_list) == 0: - # no service to stop + # no service to start return - for (order, svc) in sorted(svc_list): - svc_name = service.SERVICE_LIST[svc][0] - svchandle = ipaservices.service(svc_name) + for svc in svc_list: + svchandle = ipaservices.service(svc) try: print "Starting %s Service" % svc - svchandle.start(capture_output=get_capture_output(svc_name, options.debug)) + svchandle.start(capture_output=get_capture_output(svc, options.debug)) except: emit_err("Failed to start %s Service" % svc) emit_err("Shutting down") - for (order, svc) in sorted(svc_list): - svc_name = service.SERVICE_LIST[svc][0] - svc_off = ipaservices.service(svc_name) + for svc in svc_list: + svc_off = ipaservices.service(svc) try: svc_off.stop(capture_output=False) except: @@ -220,11 +238,10 @@ def ipa_stop(options): dirsrv = ipaservices.knownservices.dirsrv svc_list = [] try: - svc_list = get_config(dirsrv) + svc_list = get_config_from_file() except Exception, e: - # ok if dirsrv died this may fail, so let's try to quickly restart it - # and see if we can get anything. If not throw our hands up and just - # exit + # Issue reading the file ? Let's try to get data from LDAP as a + # fallback try: dirsrv.start(capture_output=False) svc_list = get_config(dirsrv) @@ -241,9 +258,8 @@ def ipa_stop(options): # no service to stop return - for (order, svc) in sorted(svc_list, reverse=True): - svc_name = service.SERVICE_LIST[svc][0] - svchandle = ipaservices.service(svc_name) + for svc in reversed(svc_list): + svchandle = ipaservices.service(svc) try: print "Stopping %s Service" % svc svchandle.stop(capture_output=False) @@ -256,58 +272,132 @@ def ipa_stop(options): except: raise IpactlError("Failed to stop Directory Service") + # remove file with list of started services + os.unlink(ipaservices.SVC_LIST_FILE) + def ipa_restart(options): dirsrv = ipaservices.knownservices.dirsrv + new_svc_list = [] + try: + new_svc_list = get_config(dirsrv) + except Exception, e: + emit_err("Failed to read data from Directory Service: " + str(e)) + emit_err("Shutting down") + try: + dirsrv.stop(capture_output=False) + except: + pass + if isinstance(e, IpactlError): + # do not display any other error message + raise IpactlError(rval=e.rval) + else: + raise IpactlError() + + old_svc_list = [] + try: + old_svc_list = get_config_from_file() + except Exception, e: + emit_err("Failed to get service list from file: " + str(e)) + # fallback to what's in LDAP + old_svc_list = new_svc_list + + # match service to start/stop + svc_list = [] + for s in new_svc_list: + if s in old_svc_list: + svc_list.append(s) + + #remove commons + for s in svc_list: + if s in old_svc_list: + old_svc_list.remove(s) + for s in svc_list: + if s in new_svc_list: + new_svc_list.remove(s) + + if len(old_svc_list) != 0: + # we need to definitely stop some services + for svc in reversed(old_svc_list): + svchandle = ipaservices.service(svc) + try: + print "Stopping %s Service" % svc + svchandle.stop(capture_output=False) + except: + emit_err("Failed to stop %s Service" % svc) + try: print "Restarting Directory Service" dirsrv.restart(capture_output=get_capture_output('dirsrv', options.debug)) except Exception, e: - raise IpactlError("Failed to restart Directory Service: " + str(e)) - - svc_list = [] - try: - svc_list = get_config(dirsrv) - except Exception, e: - emit_err("Failed to read data from Directory Service: " + str(e)) + emit_err("Failed to restart Directory Service: " + str(e)) emit_err("Shutting down") + for svc in reversed(svc_list): + svc_off = ipaservices.service(svc) + try: + svc_off.stop(capture_output=False) + except: + pass try: dirsrv.stop(capture_output=False) except: pass - if isinstance(e, IpactlError): - # do not display any other error message - raise IpactlError(rval=e.rval) - else: - raise IpactlError() + raise IpactlError("Aborting ipactl") - if len(svc_list) == 0: - # no service to stop - return + if len(svc_list) != 0: + # there are services to restart - for (order, svc) in sorted(svc_list): - svc_name = service.SERVICE_LIST[svc][0] - svchandle = ipaservices.service(svc_name) - try: - print "Restarting %s Service" % svc - svchandle.restart(capture_output=get_capture_output(svc_name, options.debug)) - except: - emit_err("Failed to restart %s Service" % svc) - emit_err("Shutting down") - for (order, svc) in sorted(svc_list): - svc_name = service.SERVICE_LIST[svc][0] - svc_off = ipaservices.service(svc_name) + for svc in svc_list: + svchandle = ipaservices.service(svc) + try: + print "Restarting %s Service" % svc + svchandle.restart(capture_output=get_capture_output(svc, options.debug)) + except: + emit_err("Failed to restart %s Service" % svc) + emit_err("Shutting down") + for svc in reversed(svc_list): + svc_off = ipaservices.service(svc) + try: + svc_off.stop(capture_output=False) + except: + pass try: - svc_off.stop(capture_output=False) + dirsrv.stop(capture_output=False) except: pass + raise IpactlError("Aborting ipactl") + + if len(new_svc_list) != 0: + # we still need to start some services + for svc in new_svc_list: + svchandle = ipaservices.service(svc) try: - dirsrv.stop(capture_output=False) + print "Starting %s Service" % svc + svchandle.start(capture_output=get_capture_output(svc, options.debug)) except: - pass - raise IpactlError("Aborting ipactl") + emit_err("Failed to start %s Service" % svc) + emit_err("Shutting down") + for svc in reversed(svc_list): + svc_off = ipaservices.service(svc) + try: + svc_off.stop(capture_output=False) + except: + pass + try: + dirsrv.stop(capture_output=False) + except: + pass + raise IpactlError("Aborting ipactl") def ipa_status(options): + + try: + svc_list = get_config_from_file() + except IpactlError, e: + raise e + except Exception, e: + raise IpactlError("Failed to get list of services to probe status: " + str(e)) + dirsrv = ipaservices.knownservices.dirsrv try: if dirsrv.is_running(): @@ -317,20 +407,11 @@ def ipa_status(options): except: raise IpactlError("Failed to get Directory Service status") - svc_list = [] - try: - svc_list = get_config(dirsrv) - except IpactlError, e: - raise e - except Exception, e: - raise IpactlError("Failed to get list of services to probe status: " + str(e)) - if len(svc_list) == 0: return - for (order, svc) in sorted(svc_list): - svc_name = service.SERVICE_LIST[svc][0] - svchandle = ipaservices.service(svc_name) + for svc in svc_list: + svchandle = ipaservices.service(svc) try: if svchandle.is_running(): print "%s Service: RUNNING" % svc -- 1.7.1 _______________________________________________ Freeipa-devel mailing list Freeipa-devel@redhat.com https://www.redhat.com/mailman/listinfo/freeipa-devel