[Freeipa-devel] [PATCH 3/3] Get list of service from LDAP only at startup
Simo Sorce
simo at redhat.com
Tue Oct 30 16:19:29 UTC 2012
From: Simo Sorce <ssorce at 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
More information about the Freeipa-devel
mailing list