mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
ds: Support renaming of a replication plugin in 389-ds
IPA topology plugin depends on the replication plugin but 389-ds cannot handle older alias querying in the plugin configuration with 'nsslapd-plugin-depends-on-named: ..' attribute See https://github.com/389ds/389-ds-base/issues/4786 for details Fixes: https://pagure.io/freeipa/issue/8799 Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Stanislav Levin <slev@altlinux.org> Reviewed-By: Christian Heimes <cheimes@redhat.com>
This commit is contained in:
parent
5250ef826e
commit
b4b2c10e23
@ -13,5 +13,5 @@ nsslapd-pluginversion: 1.0
|
|||||||
nsslapd-pluginvendor: Red Hat, Inc.
|
nsslapd-pluginvendor: Red Hat, Inc.
|
||||||
nsslapd-plugindescription: IPA Replication version plugin
|
nsslapd-plugindescription: IPA Replication version plugin
|
||||||
nsslapd-plugin-depends-on-type: database
|
nsslapd-plugin-depends-on-type: database
|
||||||
nsslapd-plugin-depends-on-named: Multimaster Replication Plugin
|
nsslapd-plugin-depends-on-named: $REPLICATION_PLUGIN
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ nsslapd-topo-plugin-shared-binddngroup: cn=replication managers,cn=sysaccounts,c
|
|||||||
nsslapd-topo-plugin-startup-delay: 20
|
nsslapd-topo-plugin-startup-delay: 20
|
||||||
nsslapd-pluginId: none
|
nsslapd-pluginId: none
|
||||||
nsslapd-plugin-depends-on-named: ldbm database
|
nsslapd-plugin-depends-on-named: ldbm database
|
||||||
nsslapd-plugin-depends-on-named: Multimaster Replication Plugin
|
nsslapd-plugin-depends-on-named: $REPLICATION_PLUGIN
|
||||||
nsslapd-pluginVersion: 1.0
|
nsslapd-pluginVersion: 1.0
|
||||||
nsslapd-pluginVendor: none
|
nsslapd-pluginVendor: none
|
||||||
nsslapd-pluginDescription: none
|
nsslapd-pluginDescription: none
|
||||||
|
@ -18,7 +18,7 @@ only: nsslapd-pluginType: betxnpreoperation
|
|||||||
dn: cn=MemberOf Plugin,cn=plugins,cn=config
|
dn: cn=MemberOf Plugin,cn=plugins,cn=config
|
||||||
only: nsslapd-pluginType: betxnpostoperation
|
only: nsslapd-pluginType: betxnpostoperation
|
||||||
|
|
||||||
dn: cn=Multimaster Replication Plugin,cn=plugins,cn=config
|
dn: cn=$REPLICATION_PLUGIN,cn=plugins,cn=config
|
||||||
only: nsslapd-pluginbetxn: on
|
only: nsslapd-pluginbetxn: on
|
||||||
|
|
||||||
dn: cn=PAM Pass Through Auth,cn=plugins,cn=config
|
dn: cn=PAM Pass Through Auth,cn=plugins,cn=config
|
||||||
|
@ -50,8 +50,8 @@ replace: nsslapd-pluginEnabled:off::on
|
|||||||
dn: cn=Managed Entries,cn=plugins,cn=config
|
dn: cn=Managed Entries,cn=plugins,cn=config
|
||||||
replace: nsslapd-pluginEnabled:off::on
|
replace: nsslapd-pluginEnabled:off::on
|
||||||
|
|
||||||
# Multimaster Replication Plugin, plugins, config
|
# Replication Plugin may be Multisupplier or Multimaster
|
||||||
dn: cn=Multimaster Replication Plugin,cn=plugins,cn=config
|
dn: cn=$REPLICATION_PLUGIN,cn=plugins,cn=config
|
||||||
replace: nsslapd-pluginEnabled:off::on
|
replace: nsslapd-pluginEnabled:off::on
|
||||||
|
|
||||||
# Roles Plugin, plugins, config
|
# Roles Plugin, plugins, config
|
||||||
|
@ -58,7 +58,7 @@ default: nsslapd-topo-plugin-shared-binddngroup: cn=replication managers,cn=sysa
|
|||||||
default: nsslapd-topo-plugin-startup-delay: 20
|
default: nsslapd-topo-plugin-startup-delay: 20
|
||||||
default: nsslapd-pluginId: none
|
default: nsslapd-pluginId: none
|
||||||
default: nsslapd-plugin-depends-on-named: ldbm database
|
default: nsslapd-plugin-depends-on-named: ldbm database
|
||||||
default: nsslapd-plugin-depends-on-named: Multimaster Replication Plugin
|
default: nsslapd-plugin-depends-on-named: $REPLICATION_PLUGIN
|
||||||
default: nsslapd-pluginVersion: 1.0
|
default: nsslapd-pluginVersion: 1.0
|
||||||
default: nsslapd-pluginVendor: none
|
default: nsslapd-pluginVendor: none
|
||||||
default: nsslapd-pluginDescription: none
|
default: nsslapd-pluginDescription: none
|
||||||
|
@ -571,6 +571,12 @@ class DsInstance(service.Service):
|
|||||||
inst.setup_ldapi()
|
inst.setup_ldapi()
|
||||||
inst.open()
|
inst.open()
|
||||||
|
|
||||||
|
def get_entry(dn, attrs):
|
||||||
|
return inst.getEntry(dn, attrlist=attrs)
|
||||||
|
|
||||||
|
self.sub_dict['REPLICATION_PLUGIN'] = (
|
||||||
|
replication.get_replication_plugin_name(get_entry))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ipadomain = IpaDomain(inst, dn=self.suffix.ldap_text())
|
ipadomain = IpaDomain(inst, dn=self.suffix.ldap_text())
|
||||||
ipadomain.create(properties={
|
ipadomain.create(properties={
|
||||||
@ -735,7 +741,7 @@ class DsInstance(service.Service):
|
|||||||
self._ldap_mod("pw-logging-conf.ldif")
|
self._ldap_mod("pw-logging-conf.ldif")
|
||||||
|
|
||||||
def __config_version_module(self):
|
def __config_version_module(self):
|
||||||
self._ldap_mod("version-conf.ldif")
|
self._ldap_mod("version-conf.ldif", self.sub_dict)
|
||||||
|
|
||||||
def __config_uuid_module(self):
|
def __config_uuid_module(self):
|
||||||
self._ldap_mod("uuid-conf.ldif")
|
self._ldap_mod("uuid-conf.ldif")
|
||||||
|
@ -232,6 +232,23 @@ def get_ds_version(conn):
|
|||||||
return vendor_version
|
return vendor_version
|
||||||
|
|
||||||
|
|
||||||
|
def get_replication_plugin_name(dirsrv_get_entry):
|
||||||
|
# Support renaming of a replication plugin in 389-ds
|
||||||
|
# IPA topology plugin depends on the replication plugin but
|
||||||
|
# 389-ds cannot handle older alias querying in the plugin
|
||||||
|
# configuration with 'nsslapd-plugin-depends-on-named: ..' attribute
|
||||||
|
#
|
||||||
|
# dirsrv_get_entry: function (dn, attrs) -> str
|
||||||
|
# returns entry dictionary
|
||||||
|
try:
|
||||||
|
entry = dirsrv_get_entry(
|
||||||
|
'cn=Multisupplier Replication Plugin,cn=plugins,cn=config',
|
||||||
|
['cn'])
|
||||||
|
return str(entry['cn'], encoding='utf-8')
|
||||||
|
except Exception:
|
||||||
|
return 'Multimaster Replication Plugin'
|
||||||
|
|
||||||
|
|
||||||
class ReplicationManager:
|
class ReplicationManager:
|
||||||
"""Manage replication agreements
|
"""Manage replication agreements
|
||||||
|
|
||||||
@ -737,8 +754,13 @@ class ReplicationManager:
|
|||||||
mtent = self.get_mapping_tree_entry()
|
mtent = self.get_mapping_tree_entry()
|
||||||
dn = mtent.dn
|
dn = mtent.dn
|
||||||
|
|
||||||
|
def get_entry(dn, attrs):
|
||||||
|
return self.conn.get_entry(DN(dn), attrs)
|
||||||
|
|
||||||
|
replication_plugin_name = get_replication_plugin_name(get_entry)
|
||||||
|
|
||||||
plgent = self.conn.get_entry(
|
plgent = self.conn.get_entry(
|
||||||
DN(('cn', 'Multimaster Replication Plugin'), ('cn', 'plugins'),
|
DN(('cn', replication_plugin_name), ('cn', 'plugins'),
|
||||||
('cn', 'config')),
|
('cn', 'config')),
|
||||||
['nsslapd-pluginPath'])
|
['nsslapd-pluginPath'])
|
||||||
path = plgent.single_value.get('nsslapd-pluginPath')
|
path = plgent.single_value.get('nsslapd-pluginPath')
|
||||||
|
@ -40,6 +40,7 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
DSE = 'dse.ldif'
|
DSE = 'dse.ldif'
|
||||||
COMPAT_DN = "cn=Schema Compatibility,cn=plugins,cn=config"
|
COMPAT_DN = "cn=Schema Compatibility,cn=plugins,cn=config"
|
||||||
|
REPL_PLUGIN_DN_TEMPLATE = "cn=Multi%s Replication Plugin,cn=plugins,cn=config"
|
||||||
|
|
||||||
|
|
||||||
class GetEntryFromLDIF(ldif.LDIFParser):
|
class GetEntryFromLDIF(ldif.LDIFParser):
|
||||||
@ -97,6 +98,7 @@ class IPAUpgrade(service.Service):
|
|||||||
self.modified = False
|
self.modified = False
|
||||||
self.serverid = serverid
|
self.serverid = serverid
|
||||||
self.schema_files = schema_files
|
self.schema_files = schema_files
|
||||||
|
self.sub_dict = dict()
|
||||||
|
|
||||||
def __start(self):
|
def __start(self):
|
||||||
srv = services.service(self.service_name, api)
|
srv = services.service(self.service_name, api)
|
||||||
@ -170,6 +172,20 @@ class IPAUpgrade(service.Service):
|
|||||||
else:
|
else:
|
||||||
self.backup_state('nsslapd-global-backend-lock', global_lock)
|
self.backup_state('nsslapd-global-backend-lock', global_lock)
|
||||||
|
|
||||||
|
# update self.sub_dict with the replication plugin name
|
||||||
|
# It may be different depending on 389-ds version
|
||||||
|
with open(self.filename, "r") as in_file:
|
||||||
|
parser = GetEntryFromLDIF(in_file, entries_dn=[])
|
||||||
|
parser.parse()
|
||||||
|
|
||||||
|
results = parser.get_results()
|
||||||
|
|
||||||
|
dn = REPL_PLUGIN_DN_TEMPLATE % "supplier"
|
||||||
|
if dn not in results:
|
||||||
|
dn = REPL_PLUGIN_DN_TEMPLATE % "master"
|
||||||
|
|
||||||
|
self.sub_dict['REPLICATION_PLUGIN'] = results[dn].get('cn')
|
||||||
|
|
||||||
with open(self.filename, "r") as in_file:
|
with open(self.filename, "r") as in_file:
|
||||||
parser = GetEntryFromLDIF(in_file, entries_dn=[COMPAT_DN])
|
parser = GetEntryFromLDIF(in_file, entries_dn=[COMPAT_DN])
|
||||||
parser.parse()
|
parser.parse()
|
||||||
@ -284,7 +300,7 @@ class IPAUpgrade(service.Service):
|
|||||||
|
|
||||||
def __upgrade(self):
|
def __upgrade(self):
|
||||||
try:
|
try:
|
||||||
ld = ldapupdate.LDAPUpdate(api=self.api)
|
ld = ldapupdate.LDAPUpdate(api=self.api, sub_dict=self.sub_dict)
|
||||||
if len(self.files) == 0:
|
if len(self.files) == 0:
|
||||||
self.files = ld.get_all_files(ldapupdate.UPDATES_DIR)
|
self.files = ld.get_all_files(ldapupdate.UPDATES_DIR)
|
||||||
self.modified = (ld.update(self.files) or self.modified)
|
self.modified = (ld.update(self.files) or self.modified)
|
||||||
|
@ -10,6 +10,8 @@ from ipapython.dn import DN
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
REPL_PLUGIN_NAME_TEMPLATE = 'Multi%s Replication Plugin'
|
||||||
|
|
||||||
@pytest.mark.tier1
|
@pytest.mark.tier1
|
||||||
class TestTopologyPlugin:
|
class TestTopologyPlugin:
|
||||||
"""
|
"""
|
||||||
@ -35,12 +37,13 @@ class TestTopologyPlugin:
|
|||||||
@pytest.mark.skipif(os.path.isfile(pwfile) is False,
|
@pytest.mark.skipif(os.path.isfile(pwfile) is False,
|
||||||
reason="You did not provide a .dmpw file with the DM password")
|
reason="You did not provide a .dmpw file with the DM password")
|
||||||
def test_topologyplugin(self):
|
def test_topologyplugin(self):
|
||||||
|
supplier = REPL_PLUGIN_NAME_TEMPLATE % 'supplier'
|
||||||
pluginattrs = {
|
pluginattrs = {
|
||||||
u'nsslapd-pluginPath': [u'libtopology'],
|
u'nsslapd-pluginPath': [u'libtopology'],
|
||||||
u'nsslapd-pluginVendor': [u'freeipa'],
|
u'nsslapd-pluginVendor': [u'freeipa'],
|
||||||
u'cn': [u'IPA Topology Configuration'],
|
u'cn': [u'IPA Topology Configuration'],
|
||||||
u'nsslapd-plugin-depends-on-named':
|
u'nsslapd-plugin-depends-on-named':
|
||||||
[u'Multimaster Replication Plugin', u'ldbm database'],
|
[supplier, u'ldbm database'],
|
||||||
u'nsslapd-topo-plugin-shared-replica-root': [u'dc=example,dc=com'],
|
u'nsslapd-topo-plugin-shared-replica-root': [u'dc=example,dc=com'],
|
||||||
u'nsslapd-pluginVersion': [u'1.0'],
|
u'nsslapd-pluginVersion': [u'1.0'],
|
||||||
u'nsslapd-topo-plugin-shared-config-base':
|
u'nsslapd-topo-plugin-shared-config-base':
|
||||||
@ -72,5 +75,13 @@ class TestTopologyPlugin:
|
|||||||
bind_pw=dm_password)
|
bind_pw=dm_password)
|
||||||
entry = self.conn.get_entry(topoplugindn)
|
entry = self.conn.get_entry(topoplugindn)
|
||||||
assert(set(entry.keys()) == set(pluginattrs.keys()))
|
assert(set(entry.keys()) == set(pluginattrs.keys()))
|
||||||
|
|
||||||
|
# Handle different names for replication plugin
|
||||||
|
key = 'nsslapd-plugin-depends-on-named'
|
||||||
|
plugin_dependencies = entry[key]
|
||||||
|
if supplier not in plugin_dependencies:
|
||||||
|
mm = REPL_PLUGIN_NAME_TEMPLATE % 'master'
|
||||||
|
pluginattrs[key] = [mm, 'ldbm database']
|
||||||
|
|
||||||
for i in checkvalues:
|
for i in checkvalues:
|
||||||
assert(set(pluginattrs[i]) == set(entry[i]))
|
assert(set(pluginattrs[i]) == set(entry[i]))
|
||||||
|
Loading…
Reference in New Issue
Block a user