[freeipa/f16] - Force to use 389-ds 1.2.10-0.8.a7 or above - Improve upgrade script to handle systemd 389-ds chang
abbra
abbra at fedoraproject.org
Wed Feb 1 19:24:16 UTC 2012
commit 29ff9b554f1f5caf87c97208fc270b6639269ec7
Author: Alexander Bokovoy <abokovoy at redhat.com>
Date: Wed Feb 1 21:22:18 2012 +0200
- Force to use 389-ds 1.2.10-0.8.a7 or above
- Improve upgrade script to handle systemd 389-ds change
- fixes FreeIPA tickets 2117 and 2300
- Fix freeipa to work with python-ldap 2.4.6
freeipa-2.1.4-inifiles-support.patch | 139 ++++++++++++++++
freeipa-2.1.4-python-ldap-2.4.6-support.patch | 26 +++
freeipa-2.1.4-upgrade-systemd.patch | 214 +++++++++++++++++++++++++
freeipa-systemd-upgrade | 73 ---------
freeipa.spec | 22 ++-
5 files changed, 395 insertions(+), 79 deletions(-)
---
diff --git a/freeipa-2.1.4-inifiles-support.patch b/freeipa-2.1.4-inifiles-support.patch
new file mode 100644
index 0000000..c4f4154
--- /dev/null
+++ b/freeipa-2.1.4-inifiles-support.patch
@@ -0,0 +1,139 @@
+From 16d3d30130215d74295e89ba5a51522eed45e180 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy at redhat.com>
+Date: Wed, 1 Feb 2012 14:20:53 +0200
+Subject: [PATCH 1/3] Add management of inifiles to allow manipulation of
+ systemd units
+
+inifile_replace_variables() works similar to config_replace_variables() but
+allows to apply changes to specific section of an inifile. Inifiles are
+commonly used by freedesktop.org software and particularly used by systemd.
+
+When modifying inifile, all changes will be applied to specific section.
+
+Also fixes corner case in config_replace_variables() which would dublicate
+variables when adding them.
+---
+ ipapython/ipautil.py | 100 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 99 insertions(+), 1 deletions(-)
+
+diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
+index 718f209b32649df23177dcab7d5105d01c0cd7bc..e141e00171cb86bec58a6be0b3e7d1f51a24faf1 100644
+--- a/ipapython/ipautil.py
++++ b/ipapython/ipautil.py
+@@ -1245,7 +1245,7 @@ $)''', re.VERBOSE)
+ new_vars = replacevars.copy()
+ new_vars.update(appendvars)
+ newvars_view = set(new_vars.keys()) - set(old_values.keys())
+- append_view = (set(appendvars.keys()) - set(replacevars.keys())) - set(old_values.keys())
++ append_view = (set(appendvars.keys()) - newvars_view)
+ for item in newvars_view:
+ new_config.write("%s=%s\n" % (item,new_vars[item]))
+ for item in append_view:
+@@ -1262,6 +1262,104 @@ $)''', re.VERBOSE)
+
+ return old_values
+
++def inifile_replace_variables(filepath, section, replacevars=dict(), appendvars=dict()):
++ """
++ Take a section-structured key=value based configuration file, and write new version
++ with certain values replaced or appended within the section
++
++ All (key,value) pairs from replacevars and appendvars that were not found
++ in the configuration file, will be added there.
++
++ It is responsibility of a caller to ensure that replacevars and
++ appendvars do not overlap.
++
++ It is responsibility of a caller to back up file.
++
++ returns dictionary of affected keys and their previous values
++
++ One have to run restore_context(filepath) afterwards or
++ security context of the file will not be correct after modification
++ """
++ pattern = re.compile('''
++(^
++ \[
++ (?P<section> .+) \]
++ (\s+((\#|;).*)?)?
++$)|(^
++ \s*
++ (?P<option> [^\#;]+?)
++ (\s*=\s*)
++ (?P<value> .+?)?
++ (\s*((\#|;).*)?)?
++$)''', re.VERBOSE)
++ def add_options(config, replacevars, appendvars, oldvars):
++ # add all options from replacevars and appendvars that were not found in the file
++ new_vars = replacevars.copy()
++ new_vars.update(appendvars)
++ newvars_view = set(new_vars.keys()) - set(oldvars.keys())
++ append_view = (set(appendvars.keys()) - newvars_view)
++ for item in newvars_view:
++ config.write("%s=%s\n" % (item,new_vars[item]))
++ for item in append_view:
++ config.write("%s=%s\n" % (item,appendvars[item]))
++
++ orig_stat = os.stat(filepath)
++ old_values = dict()
++ temp_filename = None
++ with tempfile.NamedTemporaryFile(delete=False) as new_config:
++ temp_filename = new_config.name
++ with open(filepath, 'r') as f:
++ in_section = False
++ finished = False
++ line_idx = 1
++ for line in f:
++ line_idx = line_idx + 1
++ new_line = line
++ m = pattern.match(line)
++ if m:
++ sect, option, value = m.group('section', 'option', 'value')
++ if in_section and sect is not None:
++ # End of the searched section, add remaining options
++ add_options(new_config, replacevars, appendvars, old_values)
++ finished = True
++ if sect is not None:
++ # New section is found, check whether it is the one we are looking for
++ in_section = (str(sect).lower() == str(section).lower())
++ if option is not None and in_section:
++ # Great, this is an option from the section we are loking for
++ if replacevars and option in replacevars:
++ # replace value completely
++ new_line = u"%s=%s\n" % (option, replacevars[option])
++ old_values[option] = value
++ if appendvars and option in appendvars:
++ # append a new value unless it is already existing in the original one
++ if not value:
++ new_line = u"%s=%s\n" % (option, appendvars[option])
++ elif value.find(appendvars[option]) == -1:
++ new_line = u"%s=%s %s\n" % (option, value, appendvars[option])
++ old_values[option] = value
++ new_config.write(new_line)
++ # We have finished parsing the original file.
++ # There are two remaining cases:
++ # 1. Section we were looking for was not found, we need to add it.
++ if not (in_section or finished):
++ new_config.write("[%s]\n" % (section))
++ # 2. The section is the last one but some options were not found, add them.
++ if in_section or not finished:
++ add_options(new_config, replacevars, appendvars, old_values)
++
++ new_config.flush()
++ # Make sure the resulting file is readable by others before installing it
++ os.fchmod(new_config.fileno(), orig_stat.st_mode)
++ os.fchown(new_config.fileno(), orig_stat.st_uid, orig_stat.st_gid)
++
++ # At this point new_config is closed but not removed due to 'delete=False' above
++ # Now, install the temporary file as configuration and ensure old version is available as .orig
++ # While .orig file is not used during uninstall, it is left there for administrator.
++ install_file(temp_filename, filepath)
++
++ return old_values
++
+ def backup_config_and_replace_variables(fstore, filepath, replacevars=dict(), appendvars=dict()):
+ """
+ Take a key=value based configuration file, back up it, and
+--
+1.7.8.3
+
diff --git a/freeipa-2.1.4-python-ldap-2.4.6-support.patch b/freeipa-2.1.4-python-ldap-2.4.6-support.patch
new file mode 100644
index 0000000..84e1cd1
--- /dev/null
+++ b/freeipa-2.1.4-python-ldap-2.4.6-support.patch
@@ -0,0 +1,26 @@
+From a639ff31c65b6fabfa916e0ea9256fad9e90d3cf Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy at redhat.com>
+Date: Wed, 1 Feb 2012 14:25:46 +0200
+Subject: [PATCH 2/3] Adopt to python-ldap 2.4.6 by removing unused references
+ which are not available in python-ldap anymore
+
+---
+ ipaserver/ipaldap.py | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/ipaserver/ipaldap.py b/ipaserver/ipaldap.py
+index 1820e690b10c820efcd3217801bde6b685bbf20b..89c031290acb5c041e0fa5e9412bbc85eb0288ec 100644
+--- a/ipaserver/ipaldap.py
++++ b/ipaserver/ipaldap.py
+@@ -31,7 +31,7 @@ import time
+ import struct
+ import ldap.sasl
+ import ldapurl
+-from ldap.controls import LDAPControl,DecodeControlTuples,EncodeControlTuples
++from ldap.controls import LDAPControl
+ from ldap.ldapobject import SimpleLDAPObject
+ from ipaserver import ipautil
+ from ipaserver.install import installutils
+--
+1.7.8.3
+
diff --git a/freeipa-2.1.4-upgrade-systemd.patch b/freeipa-2.1.4-upgrade-systemd.patch
new file mode 100644
index 0000000..0eb004e
--- /dev/null
+++ b/freeipa-2.1.4-upgrade-systemd.patch
@@ -0,0 +1,214 @@
+From a9c0a0bc8d3fcf27bb16a92002d944c2a71f7ce7 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy at redhat.com>
+Date: Wed, 1 Feb 2012 17:51:24 +0200
+Subject: [PATCH 3/3] 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 0000000000000000000000000000000000000000..572d69df64b335e1a06b358fc9a0f2132807d6a6
+--- /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 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 at .service'):
++ os.unlink('/etc/systemd/system/dirsrv at .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 0e476928e45be69e4aa09c5183070924a00b1269..369a1778b512fea6119e8e0f600ffda26739eb30 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 at .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 at .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 at .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 3f1fe730ebab4c0636f8c9d8d83d956da307b92b..ae06c0227aa59a46b2d4df024fc87577b8bbab29 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>@.service to /etc/systemd/system/ if it is not there
+- # 2. Make /etc/systemd/system/<service>.target.wants/ if it is not there
+- # 3. Link /etc/systemd/system/<service>.target.wants/<service>@<instance_name>.service to
+- # /etc/systemd/system/<service>@.service
+- srv_etc = os.path.join(self.SYSTEMD_ETC_PATH, self.service_name)
++ # 1. Make /etc/systemd/system/<service>.target.wants/ if it is not there
++ # 2. Link /etc/systemd/system/<service>.target.wants/<service>@<instance_name>.service to
++ # /lib/systemd/system/<service>@.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/<service>.target.wants/<service>@<instance_name>.service
+- # to /etc/systemd/system/<service>@.service
++ # to /lib/systemd/system/<service>@.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:
+--
+1.7.8.3
+
diff --git a/freeipa.spec b/freeipa.spec
index 04d7a82..7f4c417 100644
--- a/freeipa.spec
+++ b/freeipa.spec
@@ -14,14 +14,13 @@ distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
Name: freeipa
Version: 2.1.4
-Release: 4%{?dist}
+Release: 5%{?dist}
Summary: The Identity, Policy and Audit system
Group: System Environment/Base
License: GPLv3+
URL: http://www.freeipa.org/
Source0: freeipa-%{version}.tar.gz
-Source1: freeipa-systemd-upgrade
Patch0: freeipa-2.1.4-connection-failure-recovery.patch
Patch1: freeipa-2.1.4-fix-pylint-f16.patch
Patch2: freeipa-2.1.4-slapi-plugins-use-thread-safe-ldap-library.patch
@@ -29,6 +28,9 @@ Patch3: freeipa-2.1.4-selinux-web-migration-policy.patch
Patch4: freeipa-2.1.4-logging.patch
Patch5: freeipa-2.1.4-replication-addentry.patch
Patch6: freeipa-2.1.4-replica-install-services.patch
+Patch7: freeipa-2.1.4-inifiles-support.patch
+Patch8: freeipa-2.1.4-python-ldap-2.4.6-support.patch
+Patch9: freeipa-2.1.4-upgrade-systemd.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%if ! %{ONLY_CLIENT}
@@ -80,7 +82,7 @@ Requires: %{name}-python = %{version}-%{release}
Requires: %{name}-client = %{version}-%{release}
Requires: %{name}-admintools = %{version}-%{release}
Requires: %{name}-server-selinux = %{version}-%{release}
-Requires(pre): 389-ds-base >= 1.2.10-0.6.a6
+Requires(pre): 389-ds-base >= 1.2.10-0.8.a7
Requires: openldap-clients
Requires: nss
Requires: nss-tools
@@ -222,7 +224,6 @@ package.
%prep
%setup -n freeipa-%{version} -q
-cp %{SOURCE1} init/systemd/
%patch0 -p1
%patch1 -p1
%patch2 -p1
@@ -230,6 +231,9 @@ cp %{SOURCE1} init/systemd/
%patch4 -p1
%patch5 -p1
%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
%build
export CFLAGS="$CFLAGS %{optflags}"
@@ -333,8 +337,9 @@ if [ $1 -gt 1 ] ; then
# When upgrade is performed from SysV to systemd, ipa.service will be inactive
# due to https://bugzilla.redhat.com/show_bug.cgi?id=752846
# FreeIPA existing setup cannot be used without upgrade script
- /bin/systemctl --quiet is-active ipa.service >/dev/null || \
- /usr/libexec/freeipa-systemd-upgrade || :
+ # Note also it is now safe to run this script against working FreeIPA install
+ # after it has been migrated to systemd setup
+ /usr/libexec/freeipa-systemd-upgrade || :
/usr/sbin/ipa-upgradeconfig || :
/usr/sbin/ipa-ldap-updater --upgrade >/dev/null 2>&1 || :
fi
@@ -551,6 +556,11 @@ fi
%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/default.conf
%changelog
+* Wed Feb 01 2012 Alexander Bokovoy <abokovoy at redhat.com> - 2.1.4-5
+- Force to use 389-ds 1.2.10-0.8.a7 or above
+- Improve upgrade script to handle systemd 389-ds change
+- Fix freeipa to work with python-ldap 2.4.6
+
* Wed Jan 11 2012 Martin Kosek <mkosek at redhat.com> - 2.1.4-4
- Fix ipa-replica-install crashes
- Fix ipa-server-install and ipa-dns-install logging
More information about the scm-commits
mailing list