Introduce ipa control script that reads configuration off ldap

This replace the former ipactl script, as well as replace the current way ipa
components are started.

Instead of enabling each service in the system init scripts, enable only the
ipa script, and then let it start all components based on the configuration
read from the LDAP tree.

resolves: https://fedorahosted.org/freeipa/ticket/294
This commit is contained in:
Simo Sorce 2010-12-04 15:42:14 -05:00
parent ded15c72ff
commit 2efc08a6fc
10 changed files with 332 additions and 121 deletions

View File

@ -842,6 +842,10 @@ def main():
except Exception, e:
sys.exit("Configuration of client side components failed!\nipa-client-install returned: " + str(e))
#Everything installed properly, activate ipa service.
service.chkconfig_on('ipa')
print "=============================================================================="
print "Setup complete"
print ""

View File

@ -1,6 +1,7 @@
#!/bin/sh
#!/usr/bin/env python
# Authors: Simo Sorce <ssorce@redhat.com>
#
# Copyright (C) 2008 Red Hat
# Copyright (C) 2008-2010 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or
@ -16,108 +17,207 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
# IPA control to start/stop the various services required for IPA in the
# proper order
#
# Set IFS so we can do space-embedded lists of services
IFS=";"
import sys
try:
from ipaserver.install import service
from ipapython import config
from ipalib import api, errors
import logging
import ldap
import socket
import syslog
except ImportError:
print >> sys.stderr, """\
There was a problem importing one of the required Python modules. The
error was:
# start and stop are basically a reverse of each other
services_stop="ipa_kpasswd;httpd;krb5kdc;dirsrv;ntpd;named;pki-cad pki-ca"
services_start="dirsrv;ntpd;krb5kdc;named;ipa_kpasswd;httpd;pki-cad pki-ca"
%s
""" % sys.exc_value
sys.exit(1)
function is_running() {
# $1 = service to check on
# $2 = optional instance to check on, for dirsrv and pki-cad
def parse_options():
usage = "%prog start|stop|restart|status\n"
parser = config.IPAOptionParser(usage=usage,
formatter=config.IPAFormatter())
# Returns
# 0 - running
# 1 - pid but dead service
# 2 - dead but locked subsys
# 3 - stopped
# 4 - no such service
if [ "$#" = 2 ] ; then
/sbin/service $1 status $2 > /dev/null 2>&1
else
out=`/sbin/service $1 status 2>&1`
fi
case "$?" in
0)
return 0;;
1)
x=`echo $out | grep -c exists`
if [ $x -eq 1 ] ; then
return 1
else
return 4
fi
;;
2)
return 2;;
3)
return 3;;
esac
}
parser.add_option("-d", "--debug", action="store_true", dest="debug",
help="Display debugging information")
function start() {
for service in $services_start ; do
is_running $service
case "$?" in
0) # running
;;
4) # no such service
;;
*) # otherwise not running
/sbin/service $service start
;;
esac
done
}
options, args = parser.parse_args()
safe_options = parser.get_safe_opts(options)
function stop() {
for service in $services_stop ; do
is_running $service
case "$?" in
0) # running
/sbin/service $service stop
;;
*) # otherwise not running or doesn't exist
;;
esac
done
}
return safe_options, options, args
function status() {
for service in $services_start ; do
is_running $service
case "$?" in
4)
;;
*)
/sbin/service $service status
;;
esac
done
}
def emit_err(err):
syslog.syslog(syslog.LOG_ERR, err)
print err
case "$1" in
restart)
stop
start
;;
start)
start
;;
stop)
stop
;;
status)
status
;;
*)
echo "Usage: ipactl {start|stop|restart|status}"
exit 1
;;
esac
def get_config():
base = "cn=%s,cn=masters,cn=ipa,cn=etc,%s" % (socket.gethostname(),
api.env.basedn)
srcfilter = '(ipaConfigString=enabledService)'
attrs = ['cn', 'ipaConfigString']
try:
con = ldap.initialize(api.env.ldap_uri)
con.simple_bind()
res = con.search_st(base,
ldap.SCOPE_SUBTREE,
filterstr=srcfilter,
attrlist=attrs,
timeout=10)
except e:
print "Error retrieving list of services %s" % e
print "Is IPA installed ?"
return
svc_list = []
for entry in res:
name = entry[1]['cn'][0]
for p in entry[1]['ipaConfigString']:
if p.startswith('startOrder '):
order = p.split()[1]
svc_list.append((order, name))
return svc_list
def ipa_start():
try:
print "Starting Directory Service"
service.start('dirsrv')
except:
emit_err("Failed to start Directory Service")
return
svc_list = get_config()
for (order, svc) in sorted(svc_list):
svc_name = service.SERVICE_LIST[svc][0]
try:
print "Starting %s Service" % svc
service.start(svc_name)
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]
try:
service.stop(svc_name)
except:
pass
try:
service.stop('dirsrv')
except:
pass
return
def ipa_stop():
svc_list = get_config()
for (order, svc) in sorted(svc_list, reverse=True):
svc_name = service.SERVICE_LIST[svc][0]
try:
print "Stopping %s Service" % svc
service.stop(svc_name)
except:
emit_err("Failed to stop %s Service" % svc)
try:
print "Stopping Directory Service"
service.stop('dirsrv')
except:
emit_err("Failed to stop Directory Service")
return
def ipa_restart():
try:
print "Restarting Directory Service"
service.restart('dirsrv')
except:
emit_err("Failed to restart Directory Service")
return
svc_list = get_config()
for (order, svc) in sorted(svc_list):
svc_name = service.SERVICE_LIST[svc][0]
try:
print "Restarting %s Service" % svc
service.restart(svc_name)
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]
try:
service.stop(svc_name)
except:
pass
try:
service.stop('dirsrv')
except:
pass
return
def ipa_status():
try:
if service.is_running('dirsrv'):
print "Directory Service: RUNNING"
else:
print "Directory Service: STOPPED"
except:
print "Failed to get Directory Service status"
return
svc_list = get_config()
for (order, svc) in sorted(svc_list):
svc_name = service.SERVICE_LIST[svc][0]
try:
if service.is_running(svc_name):
print "%s Service: RUNNING" % svc
else:
print "%s Service: STOPPED" % svc
except:
print "Failed to get %s Service status" % svc
def main():
safe_options, options, args = parse_options()
if len(args) != 1:
sys.exit("You must specify one action")
elif args[0] != "start" and args[0] != "stop" and args[0] != "restart" and args[0] != "status":
sys.exit("Unrecognized action [" + args[0] + "]")
api.bootstrap(context='cli', debug=options.debug)
api.finalize()
syslog.openlog('ipa', syslog.LOG_NDELAY, syslog.LOG_DAEMON)
if args[0].lower() == "start":
ipa_start()
elif args[0].lower() == "stop":
ipa_stop()
elif args[0].lower() == "restart":
ipa_restart()
elif args[0].lower() == "status":
ipa_status()
syslog.closelog()
try:
if __name__ == "__main__":
sys.exit(main())
except RuntimeError, e:
print "%s" % e
sys.exit(1)
except SystemExit, e:
sys.exit(e)
except KeyboardInterrupt, e:
sys.exit(1)

45
ipa.init Executable file
View File

@ -0,0 +1,45 @@
#!/bin/sh
#
# ipa This starts and stops ipa
#
# chkconfig: - 21 79
# description: IPA Server
# processname: /usr/sbin/ns-slapd
# configdir: /etc/ipa/
# piddir: /var/run/dirsrv
#
# Source function library.
if [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
fi
# Source networking configuration.
if [ -f /etc/sysconfig/network ] ; then
. /etc/sysconfig/network
fi
# Check that networking is up.
if [ "${NETWORKING}" = "no" ]
then
echo "Networking is down"
exit 0
fi
# Lockfile
if [ -d "/var/lock/subsys" ] ; then
lockfile="/var/lock/subsys/dirsrv"
else
lockfile="/var/lock/dirsrv/lock"
fi
case "$1" in
start|stop|restart|status)
/usr/sbin/ipactl $1
;;
condrestart)
[ ! -f $lockfile ] || /usr/sbin/ipactl restart
;;
*)
echo "Usage: $0 {start|stop|status|restart|condrestart}"
exit 2
esac

View File

@ -94,6 +94,8 @@ Requires(post): selinux-policy-base
Requires: slapi-nis >= 0.15
Requires: pki-ca >= 1.3.6
Requires: pki-silent >= 1.3.4
Requires(preun): python initscripts chkconfig
Requires(postun): python initscripts chkconfig
%description server
IPA is an integrated solution to provide centrally managed Identity (machine,
@ -280,7 +282,9 @@ ln -s ../../../..%{_sysconfdir}/ipa/html/unauthorized.html \
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/
/bin/touch $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/ipa.conf
/bin/touch $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/ipa-rewrite.conf
install -m755 ipa.init $RPM_BUILD_ROOT%{_initrddir}/ipa
%endif
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/ipa/
/bin/touch $RPM_BUILD_ROOT%{_sysconfdir}/ipa/default.conf
mkdir -p %{buildroot}/%{_localstatedir}/lib/ipa-client/sysrestore
@ -296,6 +300,7 @@ rm -rf %{buildroot}
%if ! %{ONLY_CLIENT}
%post server
if [ $1 = 1 ]; then
/sbin/chkconfig --add ipa
/sbin/chkconfig --add ipa_kpasswd
fi
if [ -e /usr/share/ipa/serial ]; then
@ -305,15 +310,14 @@ fi
%preun server
if [ $1 = 0 ]; then
/sbin/chkconfig --del ipa
/sbin/chkconfig --del ipa_kpasswd
/sbin/service ipa_kpasswd stop >/dev/null 2>&1 || :
/sbin/service ipa stop >/dev/null 2>&1 || :
fi
%postun server
if [ "$1" -ge "1" ]; then
/sbin/service ipa_kpasswd condrestart >/dev/null 2>&1 || :
/sbin/service httpd condrestart >/dev/null 2>&1 || :
/sbin/service dirsrv condrestart >/dev/null 2>&1 || :
/sbin/service ipa condrestart >/dev/null 2>&1 || :
fi
%pre server-selinux
@ -373,6 +377,7 @@ fi
%{_sbindir}/ipa_kpasswd
%{_sbindir}/ipactl
%{_sbindir}/ipa-upgradeconfig
%attr(755,root,root) %{_initrddir}/ipa
%attr(755,root,root) %{_initrddir}/ipa_kpasswd
%{python_sitelib}/ipaserver/*
%dir %{_usr}/share/ipa
@ -503,6 +508,9 @@ fi
%endif
%changelog
* Tue Dec 7 2010 Simo Sorce <ssorce@redhat.com> - 1.99-33
- Add ipa init script
* Fri Nov 19 2010 Rob Crittenden <rcritten@redhat.com> - 1.99-32
- Set minimum level of 389-ds-base to 1.2.7 for enhanced memberof plugin

View File

@ -275,7 +275,10 @@ class BindInstance(service.Service):
def __enable(self):
self.backup_state("enabled", self.is_running())
self.chkconfig_on()
# We do not let the system start IPA components on its own,
# Instead we reply on the IPA init script to start only enabled
# components as found in our LDAP configuration tree
self.ldap_enable('DNS', self.fqdn, self.dm_password, self.suffix)
def __setup_sub_dict(self):
if self.forwarders:

View File

@ -242,7 +242,6 @@ class CADSInstance(service.Service):
self.step("creating directory server user", self.__create_ds_user)
self.step("creating directory server instance", self.__create_instance)
self.step("configuring directory to start on boot", self.__enable)
self.step("restarting directory server", self.__restart_instance)
self.start_creation("Configuring directory server for the CA", 30)
@ -255,13 +254,6 @@ class CADSInstance(service.Service):
SERVER_ROOT=server_root, DOMAIN=self.domain,
TIME=int(time.time()), DSPORT=self.ds_port)
def __enable(self):
name = self.service_name
self.service_name="dirsrv"
self.backup_state("enabled", self.is_enabled())
self.chkconfig_on()
self.service_name = name
def __create_ds_user(self):
user_exists = True
try:
@ -483,7 +475,11 @@ class CAInstance(service.Service):
def __enable(self):
self.backup_state("enabled", self.is_enabled())
self.chkconfig_on()
# We do not let the system start IPA components on its own,
# Instead we reply on the IPA init script to start only enabled
# components as found in our LDAP configuration tree
suffix = util.realm_to_suffix(self.realm)
self.ldap_enable('CA', self.fqdn, self.dm_password, suffix)
def __create_ca_user(self):
user_exists = True

View File

@ -295,7 +295,10 @@ class DsInstance(service.Service):
def __enable(self):
self.backup_state("enabled", self.is_enabled())
self.chkconfig_on()
# At the end of the installation ipa-server-install will enable the
# 'ipa' service wich takes care of starting/stopping dirsrv
# self.chkconfig_on()
self.chkconfig_off()
def __setup_sub_dict(self):
server_root = find_server_root()

View File

@ -91,7 +91,10 @@ class HTTPInstance(service.Service):
def __enable(self):
self.backup_state("enabled", self.is_running())
self.chkconfig_on()
# We do not let the system start IPA components on its own,
# Instead we reply on the IPA init script to start only enabled
# components as found in our LDAP configuration tree
self.ldap_enable('HTTP', self.fqdn, self.dm_password, self.suffix)
def __selinux_config(self):
selinux=0

View File

@ -203,8 +203,7 @@ class KrbInstance(service.Service):
self.start_creation("Configuring Kerberos KDC", 30)
self.kpasswd = KpasswdInstance()
self.kpasswd.create_instance()
self.kpasswd.create_instance('KPASSWD', self.fqdn, self.admin_password, self.suffix)
def create_replica(self, ds_user, realm_name, host_name,
domain_name, admin_password,
@ -233,7 +232,7 @@ class KrbInstance(service.Service):
self.start_creation("Configuring Kerberos KDC", 30)
self.kpasswd = KpasswdInstance()
self.kpasswd.create_instance()
self.kpasswd.create_instance('KPASSWD', self.fqdn, self.admin_password, self.suffix)
def __copy_ldap_passwd(self, filename):
self.fstore.backup_file("/var/kerberos/krb5kdc/ldappwd")
@ -258,7 +257,10 @@ class KrbInstance(service.Service):
def __enable(self):
self.backup_state("enabled", self.is_enabled())
self.chkconfig_on()
# We do not let the system start IPA components on its own,
# Instead we reply on the IPA init script to start only enabled
# components as found in our LDAP configuration tree
self.ldap_enable('KDC', self.fqdn, self.admin_password, self.suffix)
def __start_instance(self):
try:

View File

@ -29,6 +29,13 @@ import base64
import time
import datetime
SERVICE_LIST = {
'KDC':('krb5kdc', 10),
'KPASSWD':('ipa_kpasswd', 20),
'DNS':('named', 30),
'HTTP':('httpd', 40),
'CA':('pki_cad', 50)
}
def stop(service_name, instance_name=""):
ipautil.run(["/sbin/service", service_name, "stop", instance_name])
@ -263,8 +270,44 @@ class Service:
self.steps = []
def __get_conn(self, dm_password):
try:
conn = ipaldap.IPAdmin("127.0.0.1")
conn.simple_bind_s("cn=directory manager", dm_password)
except Exception, e:
logging.critical("Could not connect to the Directory Server on %s: %s" % (self.fqdn, str(e)))
raise e
return conn
def ldap_enable(self, name, fqdn, dm_password, ldap_suffix):
self.chkconfig_off()
conn = self.__get_conn(dm_password)
entry_name = "cn=%s,cn=%s,%s,%s" % (name, fqdn,
"cn=masters,cn=ipa,cn=etc",
ldap_suffix)
order = SERVICE_LIST[name][1]
entry = ipaldap.Entry(entry_name)
entry.setValues("objectclass",
"nsContainer", "ipaConfigObject")
entry.setValues("cn", name)
entry.setValues("ipaconfigstring",
"enabledService", "startOrder " + str(order))
try:
conn.add_s(entry)
except ldap.ALREADY_EXISTS:
logging.critical("failed to add %s Service startup entry" % name)
raise e
class SimpleServiceInstance(Service):
def create_instance(self):
def create_instance(self, gensvc_name=None, fqdn=None, dm_password=None, ldap_suffix=None):
self.gensvc_name = gensvc_name
self.fqdn = fqdn
self.dm_password = dm_password
self.suffix = ldap_suffix
self.step("starting %s " % self.service_name, self.__start)
self.step("configuring %s to start on boot" % self.service_name, self.__enable)
self.start_creation("Configuring %s" % self.service_name)
@ -276,7 +319,11 @@ class SimpleServiceInstance(Service):
def __enable(self):
self.chkconfig_add()
self.backup_state("enabled", self.is_enabled())
self.chkconfig_on()
if self.gensvc_name == None:
self.chkconfig_on()
else:
self.ldap_enable(self.gensvc_name, self.fqdn,
self.dm_password, self.suffix)
def uninstall(self):
if self.is_configured():