From 8bba212c80163648ed3a6ba9cf77b1369a198053 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 1 Feb 2012 17:51:24 +0200 Subject: Handle upgrade issues with systemd in Fedora 16 and above Since 389-ds-base-1.2.10-0.8.a7 Directory Server's systemd settings are configured via /etc/sysconfig/dirsrv.systemd. It means logic change in systemd/fedora16 platform of FreeIPA. Additionally, existing installs need to be handled during upgrade. Fixes: https://fedorahosted.org/freeipa/ticket/2117 https://fedorahosted.org/freeipa/ticket/2300 --- init/systemd/freeipa-systemd-upgrade | 96 ++++++++++++++++++++++++++++++++++++ ipapython/platform/fedora16.py | 22 ++++----- ipapython/platform/systemd.py | 16 +++--- 3 files changed, 113 insertions(+), 21 deletions(-) create mode 100755 init/systemd/freeipa-systemd-upgrade diff --git a/init/systemd/freeipa-systemd-upgrade b/init/systemd/freeipa-systemd-upgrade new file mode 100755 index 000000000..e662d2835 --- /dev/null +++ b/init/systemd/freeipa-systemd-upgrade @@ -0,0 +1,96 @@ +#! /usr/bin/python -E +from ipaserver.install.krbinstance import update_key_val_in_file +from ipapython import ipautil, config +from ipapython import services as ipaservices +import os, platform + +def convert_java_link(foo, topdir, filepaths): + cwd = os.getcwd() + os.chdir(topdir) + for filepath in filepaths: + # All this shouldn't happen because java system upgrade should properly + # move files and symlinks but if this is a broken link + if os.path.islink(filepath): + print " Checking %s ... " % (filepath), + if not os.path.exists(filepath): + rpath = os.path.realpath(filepath) + # .. and it points to jss in /usr/lib + if rpath.find('/usr/lib/') != -1 and rpath.find('jss') != -1: + base = os.path.basename(rpath) + bitness = platform.architecture()[0][:2] + # rewrite it to /usr/lib64 for x86_64 platform + if bitness == '64': + npath = "/usr/lib%s/jss/%s" % (bitness, base) + os.unlink(filepath) + os.symlink(npath, filepath) + print "%s -> %s" % (filepath, npath) + else: + print "Ok" + else: + print "Ok" + else: + print "Ok" + os.chdir(cwd) + +# 0. Init config +try: + config.init_config() +except config.IPAConfigError, e: + # No configured IPA install, no need to upgrade anything + exit(0) + +# 1. Convert broken symlinks, if any, in /var/lib/pki-ca +if os.path.exists('/var/lib/pki-ca/common/lib'): + print "Analyzing symlinks in PKI-CA install" + os.path.walk('/var/lib/pki-ca/common/lib', convert_java_link, None) + +try: + print "Found IPA server for domain %s" % (config.config.default_realm) + # 1. Make sure Dogtag instance (if exists) has proper OIDs for IPA CA + ipa_ca_cfg = "/var/lib/pki-ca/profiles/ca/caIPAserviceCert.cfg" + if os.path.exists(ipa_ca_cfg): + print "Make sure PKI-CA has Extended Key Usage OIDs for the certificates (Server and Client Authentication)", + key = 'policyset.serverCertSet.7.default.params.exKeyUsageOIDs' + value = '1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2' + replacevars = {key:value} + appendvars = {} + old_values = ipautil.config_replace_variables(ipa_ca_cfg, replacevars=replacevars, appendvars=appendvars) + ipaservices.restore_context(ipa_ca_cfg) + if key in old_values and old_values[key] != value: + print + print " WARNING: Previously issued certificate didn't have both Server and Client Authentication usage" + print " Old usage OID(s): %(oids)s" % (old_values[key]) + print " Please make sure to revoke old certificates and re-issue them again to add both usages when needed" + ipaservices.service('pki-cad').restart() + else: + print "... ok" + print "Converting services setup to systemd" + # 2. Upgrade /etc/sysconfig/dirsrv for systemd + print " Upgrade /etc/sysconfig/dirsrv" + update_key_val_in_file("/etc/sysconfig/dirsrv", "KRB5_KTNAME", "/etc/dirsrv/ds.keytab") + update_key_val_in_file("/etc/sysconfig/dirsrv", "export KRB5_KTNAME", "/etc/dirsrv/ds.keytab") + # 3. Upgrade /etc/sysconfig/krb5kdc for systemd + print " Upgrade /etc/sysconfig/krb5kdc" + replacevars = {'KRB5REALM':config.config.default_realm} + appendvars = {} + ipautil.config_replace_variables("/etc/sysconfig/krb5kdc", + replacevars=replacevars, appendvars=appendvars) + ipaservices.restore_context("/etc/sysconfig/krb5kdc") + # 4. Enable DS instances: + # when enabling DS instances we'll also do configure /etc/sysconfig/dirsrv.systemd + # which comes with 389-ds-base-1.2.10-0.8.a7 on F-16 and later. This is handled in + # fedora16 platform code + realm = config.config.default_realm.upper().replace('.','-') + print " Re-enable Directory server instances PKI-IPA and %s " % (realm) + if os.path.exists('/etc/systemd/system/dirsrv@.service'): + os.unlink('/etc/systemd/system/dirsrv@.service') + ipaservices.knownservices.dirsrv.enable(realm) + ipaservices.knownservices.dirsrv.enable("PKI-IPA") + # 4. Enable FreeIPA + print " Re-enable IPA service" + ipaservices.knownservices.ipa.enable() +except: + pass + +finally: + print "Finished." diff --git a/ipapython/platform/fedora16.py b/ipapython/platform/fedora16.py index 0e476928e..369a1778b 100644 --- a/ipapython/platform/fedora16.py +++ b/ipapython/platform/fedora16.py @@ -59,24 +59,24 @@ class Fedora16Service(systemd.SystemdService): super(Fedora16Service, self).__init__(service_name) # Special handling of directory server service -# LimitNOFILE needs to be increased or any value set in the directory for this value will fail -# Read /lib/systemd/system/dirsrv@.service for details. -# We do modification of LimitNOFILE on service.enable() but we also need to explicitly enable instances -# to install proper symlinks as dirsrv.target.wants/ dependencies. Unfortunately, ipa-server-install -# does not do explicit dirsrv.enable() because the service startup is handled by ipactl. +# +# We need to explicitly enable instances to install proper symlinks as dirsrv.target.wants/ +# dependencies. Standard systemd service class does it on #enable() method call. Unfortunately, +# ipa-server-install does not do explicit dirsrv.enable() because the service startup is handled by ipactl. +# # If we wouldn't do this, our instances will not be started as systemd would not have any clue # about instances (PKI-IPA and the domain we serve) at all. Thus, hook into dirsrv.restart(). class Fedora16DirectoryService(Fedora16Service): def enable(self, instance_name=""): super(Fedora16DirectoryService, self).enable(instance_name) - srv_etc = os.path.join(self.SYSTEMD_ETC_PATH, self.service_name) - if os.path.exists(srv_etc): + dirsrv_systemd = "/etc/sysconfig/dirsrv.systemd" + if os.path.exists(dirsrv_systemd): # We need to enable LimitNOFILE=8192 in the dirsrv@.service - # We rely on the fact that [Service] section is the last one - # and if variable is not there, it will be added as the last line + # Since 389-ds-base-1.2.10-0.8.a7 the configuration of the service parameters is performed + # via /etc/sysconfig/dirsrv.systemd file which is imported by systemd into dirsrv@.service unit replacevars = {'LimitNOFILE':'8192'} - ipautil.config_replace_variables(srv_etc, replacevars=replacevars) - redhat.restore_context(srv_etc) + ipautil.inifile_replace_variables(dirsrv_systemd, 'service', replacevars=replacevars) + redhat.restore_context(dirsrv_systemd) ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],raiseonerr=False) def restart(self, instance_name="", capture_output=True): diff --git a/ipapython/platform/systemd.py b/ipapython/platform/systemd.py index 3f1fe730e..ae06c0227 100644 --- a/ipapython/platform/systemd.py +++ b/ipapython/platform/systemd.py @@ -137,16 +137,12 @@ class SystemdService(base.PlatformService): if len(instance_name) > 0 and l > 1: # New instance, we need to do following: - # 1. Copy @.service to /etc/systemd/system/ if it is not there - # 2. Make /etc/systemd/system/.target.wants/ if it is not there - # 3. Link /etc/systemd/system/.target.wants/@.service to - # /etc/systemd/system/@.service - srv_etc = os.path.join(self.SYSTEMD_ETC_PATH, self.service_name) + # 1. Make /etc/systemd/system/.target.wants/ if it is not there + # 2. Link /etc/systemd/system/.target.wants/@.service to + # /lib/systemd/system/@.service srv_tgt = os.path.join(self.SYSTEMD_ETC_PATH, self.SYSTEMD_SRV_TARGET % (elements[0])) srv_lnk = os.path.join(srv_tgt, self.service_instance(instance_name)) try: - if not ipautil.file_exists(srv_etc): - shutil.copy(self.lib_path, srv_etc) if not ipautil.dir_exists(srv_tgt): os.mkdir(srv_tgt) if os.path.exists(srv_lnk): @@ -156,11 +152,11 @@ class SystemdService(base.PlatformService): # object does not exist _or_ is a broken link if not os.path.islink(srv_lnk): # if it truly does not exist, make a link - os.symlink(srv_etc, srv_lnk) + os.symlink(self.lib_path, srv_lnk) else: # Link exists and it is broken, make new one os.unlink(srv_lnk) - os.symlink(srv_etc, srv_lnk) + os.symlink(self.lib_path, srv_lnk) ipautil.run(["/bin/systemctl", "--system", "daemon-reload"]) except: pass @@ -172,7 +168,7 @@ class SystemdService(base.PlatformService): if instance_name != "" and len(elements) > 1: # Remove instance, we need to do following: # Remove link from /etc/systemd/system/.target.wants/@.service - # to /etc/systemd/system/@.service + # to /lib/systemd/system/@.service srv_tgt = os.path.join(self.SYSTEMD_ETC_PATH, self.SYSTEMD_SRV_TARGET % (elements[0])) srv_lnk = os.path.join(srv_tgt, self.service_instance(instance_name)) try: -- cgit