mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Move Managed Entries into their own container in the replicated space.
Repoint cn=Managed Entries,cn=plugins,cn=config in common_setup Create: cn=Managed Entries,cn=etc,$SUFFIX Create: cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX Create: cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX Create method for dynamically migrating any and all custom Managed Entries from the cn=config space into the new container. Separate the connection creation during update so that a restart can be performed to initialize changes before performing a delete. Add wait_for_open_socket() method in installutils https://fedorahosted.org/freeipa/ticket/1708
This commit is contained in:
parent
7c50d17983
commit
3b633d559c
@ -42,6 +42,8 @@ app_DATA = \
|
|||||||
schema_compat.uldif \
|
schema_compat.uldif \
|
||||||
ldapi.ldif \
|
ldapi.ldif \
|
||||||
wsgi.py \
|
wsgi.py \
|
||||||
|
repoint-managed-entries.ldif \
|
||||||
|
managed-entries.ldif \
|
||||||
user_private_groups.ldif \
|
user_private_groups.ldif \
|
||||||
host_nis_groups.ldif \
|
host_nis_groups.ldif \
|
||||||
uuid-ipauniqueid.ldif \
|
uuid-ipauniqueid.ldif \
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
dn: cn=NGP HGP Template,cn=etc,$SUFFIX
|
dn: cn=NGP HGP Template,cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
changetype: add
|
changetype: add
|
||||||
objectclass: mepTemplateEntry
|
objectclass: mepTemplateEntry
|
||||||
cn: NGP HGP Template
|
cn: NGP HGP Template
|
||||||
@ -13,11 +13,11 @@ mepMappedAttr: description: ipaNetgroup $$cn
|
|||||||
|
|
||||||
# Changes to this definition need to be reflected in
|
# Changes to this definition need to be reflected in
|
||||||
# updates/20-host_nis_groups.update
|
# updates/20-host_nis_groups.update
|
||||||
dn: cn=NGP Definition,cn=Managed Entries,cn=plugins,cn=config
|
dn: cn=NGP Definition,cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
changetype: add
|
changetype: add
|
||||||
objectclass: extensibleObject
|
objectclass: extensibleObject
|
||||||
cn: NGP Definition
|
cn: NGP Definition
|
||||||
originScope: cn=hostgroups,cn=accounts,$SUFFIX
|
originScope: cn=hostgroups,cn=accounts,$SUFFIX
|
||||||
originFilter: objectclass=ipahostgroup
|
originFilter: objectclass=ipahostgroup
|
||||||
managedBase: cn=ng,cn=alt,$SUFFIX
|
managedBase: cn=ng,cn=alt,$SUFFIX
|
||||||
managedTemplate: cn=NGP HGP Template,cn=etc,$SUFFIX
|
managedTemplate: cn=NGP HGP Template,cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
17
install/share/managed-entries.ldif
Normal file
17
install/share/managed-entries.ldif
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
dn: cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
changetype: add
|
||||||
|
objectClass: nsContainer
|
||||||
|
objectClass: top
|
||||||
|
cn: Managed Entries
|
||||||
|
|
||||||
|
dn: cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
changetype: add
|
||||||
|
objectClass: nsContainer
|
||||||
|
objectClass: top
|
||||||
|
cn: Templates
|
||||||
|
|
||||||
|
dn: cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
changetype: add
|
||||||
|
objectClass: nsContainer
|
||||||
|
objectClass: top
|
||||||
|
cn: Definitions
|
5
install/share/repoint-managed-entries.ldif
Normal file
5
install/share/repoint-managed-entries.ldif
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Repoint Managed Entries to the replicated cn=etc space
|
||||||
|
dn: cn=Managed Entries,cn=plugins,cn=config
|
||||||
|
changetype: modify
|
||||||
|
add: nsslapd-pluginConfigArea
|
||||||
|
nsslapd-pluginConfigArea: cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX
|
@ -1,4 +1,4 @@
|
|||||||
dn: cn=UPG Template,cn=etc,$SUFFIX
|
dn: cn=UPG Template,cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
changetype: add
|
changetype: add
|
||||||
objectclass: mepTemplateEntry
|
objectclass: mepTemplateEntry
|
||||||
cn: UPG Template
|
cn: UPG Template
|
||||||
@ -12,12 +12,12 @@ mepMappedAttr: description: User private group for $$uid
|
|||||||
|
|
||||||
# Changes to this definition need to be reflected in
|
# Changes to this definition need to be reflected in
|
||||||
# updates/20-user_private_groups.update
|
# updates/20-user_private_groups.update
|
||||||
dn: cn=UPG Definition,cn=Managed Entries,cn=plugins,cn=config
|
dn: cn=UPG Definition,cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
changetype: add
|
changetype: add
|
||||||
objectclass: extensibleObject
|
objectclass: extensibleObject
|
||||||
cn: UPG Definition
|
cn: UPG Definition
|
||||||
originScope: cn=users,cn=accounts,$SUFFIX
|
originScope: cn=users,cn=accounts,$SUFFIX
|
||||||
originFilter: (&(objectclass=posixAccount)(!(description=__no_upg__)))
|
originFilter: (&(objectclass=posixAccount)(!(description=__no_upg__)))
|
||||||
managedBase: cn=groups,cn=accounts,$SUFFIX
|
managedBase: cn=groups,cn=accounts,$SUFFIX
|
||||||
managedTemplate: cn=UPG Template,cn=etc,$SUFFIX
|
managedTemplate: cn=UPG Template,cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
|
||||||
|
17
install/updates/19-managed-entries.update
Normal file
17
install/updates/19-managed-entries.update
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
dn: cn=Managed Entries,cn=plugins,cn=config
|
||||||
|
only: nsslapd-pluginConfigArea: 'cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX'
|
||||||
|
|
||||||
|
dn: cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
default: objectClass: nsContainer
|
||||||
|
default: objectClass: top
|
||||||
|
default: cn: Managed Entries
|
||||||
|
|
||||||
|
dn: cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
default: objectClass: nsContainer
|
||||||
|
default: objectClass: top
|
||||||
|
default: cn: Templates
|
||||||
|
|
||||||
|
dn: cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
default: objectClass: nsContainer
|
||||||
|
default: objectClass: top
|
||||||
|
default: cn: Definitions
|
@ -2,14 +2,22 @@
|
|||||||
# This is required for replication. The template entry will get
|
# This is required for replication. The template entry will get
|
||||||
# replicated but the plugin configuration will not.
|
# replicated but the plugin configuration will not.
|
||||||
|
|
||||||
dn: cn=NGP Definition,cn=Managed Entries,cn=plugins,cn=config
|
dn: cn=NGP HGP Template,cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
default:objectclass: mepTemplateEntry
|
||||||
|
default:cn: NGP HGP Template
|
||||||
|
default:mepRDNAttr: cn
|
||||||
|
default:mepStaticAttr: ipaUniqueId: autogenerate
|
||||||
|
default:mepStaticAttr: objectclass: ipanisnetgroup
|
||||||
|
default:mepStaticAttr: objectclass: ipaobject
|
||||||
|
default:mepStaticAttr: nisDomainName: $DOMAIN
|
||||||
|
default:mepMappedAttr: cn: $$cn
|
||||||
|
default:mepMappedAttr: memberHost: $$dn
|
||||||
|
default:mepMappedAttr: description: ipaNetgroup $$cn
|
||||||
|
|
||||||
|
dn: cn=NGP Definition,cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
default:objectclass: extensibleObject
|
default:objectclass: extensibleObject
|
||||||
default:cn: NGP Definition
|
only:cn: NGP Definition
|
||||||
default:originScope: cn=hostgroups,cn=accounts,$SUFFIX
|
default:originScope: cn=hostgroups,cn=accounts,$SUFFIX
|
||||||
default:originFilter: objectclass=ipahostgroup
|
default:originFilter: objectclass=ipahostgroup
|
||||||
default:managedBase: cn=ng,cn=alt,$SUFFIX
|
default:managedBase: cn=ng,cn=alt,$SUFFIX
|
||||||
default:managedTemplate: cn=NGP HGP Template,cn=etc,$SUFFIX
|
default:managedTemplate: cn=NGP HGP Template,cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
|
||||||
# Fix an existing configuration with the wrong cn
|
|
||||||
dn: cn=NGP Definition,cn=Managed Entries,cn=plugins,cn=config
|
|
||||||
only:cn: NGP Definition
|
|
||||||
|
@ -2,10 +2,23 @@
|
|||||||
# This is required for replication. The template entry will get
|
# This is required for replication. The template entry will get
|
||||||
# replicated but the plugin configuration will not.
|
# replicated but the plugin configuration will not.
|
||||||
|
|
||||||
dn: cn=UPG Definition,cn=Managed Entries,cn=plugins,cn=config
|
dn: cn=UPG Template,cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
default:objectclass: mepTemplateEntry
|
||||||
|
default:cn: UPG Template
|
||||||
|
default:mepRDNAttr: cn
|
||||||
|
default:mepStaticAttr: objectclass: posixgroup
|
||||||
|
default:mepStaticAttr: objectclass: ipaobject
|
||||||
|
default:mepStaticAttr: ipaUniqueId: autogenerate
|
||||||
|
default:mepMappedAttr: cn: $$uid
|
||||||
|
default:mepMappedAttr: gidNumber: $$uidNumber
|
||||||
|
default:mepMappedAttr: description: User private group for $$uid
|
||||||
|
|
||||||
|
|
||||||
|
dn: cn=UPG Definition,cn=Definitions,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
default:objectclass: extensibleObject
|
default:objectclass: extensibleObject
|
||||||
|
replace:originFilter:objectclass=posixAccount::(&(objectclass=posixAccount)(!(description=__no_upg__)))
|
||||||
default:cn: UPG Definition
|
default:cn: UPG Definition
|
||||||
default:originScope: cn=users,cn=accounts,$SUFFIX
|
default:originScope: cn=users,cn=accounts,$SUFFIX
|
||||||
default:originFilter: (&(objectclass=posixAccount)(!(description=__no_upg__)))
|
default:originFilter: objectclass=posixAccount
|
||||||
default:managedBase: cn=groups,cn=accounts,$SUFFIX
|
default:managedBase: cn=groups,cn=accounts,$SUFFIX
|
||||||
default:managedTemplate: cn=UPG Template,cn=etc,$SUFFIX
|
default:managedTemplate: cn=UPG Template,cn=Templates,cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
dn: cn=UPG Definition,cn=Managed Entries,cn=plugins,cn=config
|
|
||||||
replace: originFilter:objectclass=posixAccount::(&(objectclass=posixAccount)(!(description=__no_upg__)))
|
|
@ -7,6 +7,7 @@ app_DATA = \
|
|||||||
10-RFC4876.update \
|
10-RFC4876.update \
|
||||||
10-config.update \
|
10-config.update \
|
||||||
10-sudo.update \
|
10-sudo.update \
|
||||||
|
19-managed-entries.update \
|
||||||
20-aci.update \
|
20-aci.update \
|
||||||
20-dna.update \
|
20-dna.update \
|
||||||
20-host_nis_groups.update \
|
20-host_nis_groups.update \
|
||||||
@ -22,7 +23,6 @@ app_DATA = \
|
|||||||
50-lockout-policy.update \
|
50-lockout-policy.update \
|
||||||
50-groupuuid.update \
|
50-groupuuid.update \
|
||||||
50-hbacservice.update \
|
50-hbacservice.update \
|
||||||
50-suppress-upg.update \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
@ -201,6 +201,7 @@ class DsInstance(service.Service):
|
|||||||
self.step("configuring ssl for ds instance", self.__enable_ssl)
|
self.step("configuring ssl for ds instance", self.__enable_ssl)
|
||||||
self.step("configuring certmap.conf", self.__certmap_conf)
|
self.step("configuring certmap.conf", self.__certmap_conf)
|
||||||
self.step("configure autobind for root", self.__root_autobind)
|
self.step("configure autobind for root", self.__root_autobind)
|
||||||
|
self.step("configure new location for managed entries", self.__repoint_managed_entries)
|
||||||
self.step("restarting directory server", self.__restart_instance)
|
self.step("restarting directory server", self.__restart_instance)
|
||||||
|
|
||||||
def __common_post_setup(self):
|
def __common_post_setup(self):
|
||||||
@ -237,6 +238,7 @@ class DsInstance(service.Service):
|
|||||||
self.step("adding default layout", self.__add_default_layout)
|
self.step("adding default layout", self.__add_default_layout)
|
||||||
self.step("adding delegation layout", self.__add_delegation_layout)
|
self.step("adding delegation layout", self.__add_delegation_layout)
|
||||||
self.step("adding replication acis", self.__add_replication_acis)
|
self.step("adding replication acis", self.__add_replication_acis)
|
||||||
|
self.step("creating container for managed entries", self.__managed_entries)
|
||||||
self.step("configuring user private groups", self.__user_private_groups)
|
self.step("configuring user private groups", self.__user_private_groups)
|
||||||
self.step("configuring netgroups from hostgroups", self.__host_nis_groups)
|
self.step("configuring netgroups from hostgroups", self.__host_nis_groups)
|
||||||
self.step("creating default Sudo bind user", self.__add_sudo_binduser)
|
self.step("creating default Sudo bind user", self.__add_sudo_binduser)
|
||||||
@ -277,8 +279,6 @@ class DsInstance(service.Service):
|
|||||||
# See LDIFs for automember configuration during replica install
|
# See LDIFs for automember configuration during replica install
|
||||||
self.step("setting Auto Member configuration", self.__add_replica_automember_config)
|
self.step("setting Auto Member configuration", self.__add_replica_automember_config)
|
||||||
|
|
||||||
# Managed Entries configuration is done via update files
|
|
||||||
|
|
||||||
self.__common_post_setup()
|
self.__common_post_setup()
|
||||||
|
|
||||||
self.start_creation("Configuring directory server", 60)
|
self.start_creation("Configuring directory server", 60)
|
||||||
@ -485,6 +485,16 @@ class DsInstance(service.Service):
|
|||||||
def __config_lockout_module(self):
|
def __config_lockout_module(self):
|
||||||
self._ldap_mod("lockout-conf.ldif")
|
self._ldap_mod("lockout-conf.ldif")
|
||||||
|
|
||||||
|
def __repoint_managed_entries(self):
|
||||||
|
if not has_managed_entries(self.fqdn, self.dm_password):
|
||||||
|
raise errors.NotFound(reason='Missing Managed Entries Plugin')
|
||||||
|
self._ldap_mod("repoint-managed-entries.ldif", self.sub_dict)
|
||||||
|
|
||||||
|
def __managed_entries(self):
|
||||||
|
if not has_managed_entries(self.fqdn, self.dm_password):
|
||||||
|
raise errors.NotFound(reason='Missing Managed Entries Plugin')
|
||||||
|
self._ldap_mod("managed-entries.ldif", self.sub_dict)
|
||||||
|
|
||||||
def __user_private_groups(self):
|
def __user_private_groups(self):
|
||||||
if not has_managed_entries(self.fqdn, self.dm_password):
|
if not has_managed_entries(self.fqdn, self.dm_password):
|
||||||
raise errors.NotFound(reason='Missing Managed Entries Plugin')
|
raise errors.NotFound(reason='Missing Managed Entries Plugin')
|
||||||
|
@ -440,6 +440,27 @@ def wait_for_open_ports(host, ports, timeout=0):
|
|||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
def wait_for_open_socket(socket_name, timeout=0):
|
||||||
|
"""
|
||||||
|
Wait until the specified socket on the local host is open. Timeout
|
||||||
|
in seconds may be specified to limit the wait.
|
||||||
|
"""
|
||||||
|
op_timeout = time.time() + timeout
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
s = socket.socket(socket.AF_UNIX)
|
||||||
|
s.connect(socket_name)
|
||||||
|
s.close()
|
||||||
|
break;
|
||||||
|
except socket.error, e:
|
||||||
|
if e.errno == 111: # 111: Connection refused
|
||||||
|
if timeout and time.time() > op_timeout: # timeout exceeded
|
||||||
|
raise e
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
def resolve_host(host_name):
|
def resolve_host(host_name):
|
||||||
try:
|
try:
|
||||||
addrinfos = socket.getaddrinfo(host_name, None,
|
addrinfos = socket.getaddrinfo(host_name, None,
|
||||||
|
@ -26,6 +26,7 @@ UPDATES_DIR="/usr/share/ipa/updates/"
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
from ipaserver.install import installutils
|
from ipaserver.install import installutils
|
||||||
|
from ipaserver.install import service
|
||||||
from ipaserver import ipaldap
|
from ipaserver import ipaldap
|
||||||
from ipapython import entity, ipautil
|
from ipapython import entity, ipautil
|
||||||
from ipalib import util
|
from ipalib import util
|
||||||
@ -48,6 +49,24 @@ class BadSyntax(Exception):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return repr(self.value)
|
return repr(self.value)
|
||||||
|
|
||||||
|
class IPARestart(service.Service):
|
||||||
|
"""
|
||||||
|
Restart the 389 DS service prior to performing deletions.
|
||||||
|
"""
|
||||||
|
def __init__(self, live_run=True):
|
||||||
|
"""
|
||||||
|
This class is present to provide ldapupdate the means to
|
||||||
|
restart 389 DS to apply updates prior to performing deletes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
service.Service.__init__(self, "dirsrv")
|
||||||
|
self.live_run = live_run
|
||||||
|
|
||||||
|
def create_instance(self):
|
||||||
|
self.step("stopping directory server", self.stop)
|
||||||
|
self.step("starting directory server", self.start)
|
||||||
|
self.start_creation("Restarting IPA to initialize updates before performing deletes:")
|
||||||
|
|
||||||
class LDAPUpdate:
|
class LDAPUpdate:
|
||||||
def __init__(self, dm_password, sub_dict={}, live_run=True,
|
def __init__(self, dm_password, sub_dict={}, live_run=True,
|
||||||
online=True, ldapi=False):
|
online=True, ldapi=False):
|
||||||
@ -64,7 +83,6 @@ class LDAPUpdate:
|
|||||||
self.modified = False
|
self.modified = False
|
||||||
self.online = online
|
self.online = online
|
||||||
self.ldapi = ldapi
|
self.ldapi = ldapi
|
||||||
|
|
||||||
self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
|
self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
|
||||||
|
|
||||||
if sub_dict.get("REALM"):
|
if sub_dict.get("REALM"):
|
||||||
@ -418,6 +436,54 @@ class LDAPUpdate:
|
|||||||
|
|
||||||
return self.conn.getList(dn, scope, searchfilter, sattrs)
|
return self.conn.getList(dn, scope, searchfilter, sattrs)
|
||||||
|
|
||||||
|
def __update_managed_entries(self):
|
||||||
|
"""Update and move legacy Managed Entry Plugins."""
|
||||||
|
|
||||||
|
suffix = ipautil.realm_to_suffix(self.realm)
|
||||||
|
searchfilter = '(objectclass=*)'
|
||||||
|
definitions_managed_entries = []
|
||||||
|
old_template_container = 'cn=etc,%s' % suffix
|
||||||
|
old_definition_container = 'cn=Managed Entries,cn=plugins,cn=config'
|
||||||
|
new = 'cn=Managed Entries,cn=etc,%s' % suffix
|
||||||
|
sub = ['cn=Definitions,', 'cn=Templates,']
|
||||||
|
new_managed_entries = []
|
||||||
|
old_templates = []
|
||||||
|
template = None
|
||||||
|
try:
|
||||||
|
definitions_managed_entries = self.conn.getList(old_definition_container, ldap.SCOPE_ONELEVEL, searchfilter,[])
|
||||||
|
except errors.NotFound, e:
|
||||||
|
return new_managed_entries
|
||||||
|
for entry in definitions_managed_entries:
|
||||||
|
new_definition = {}
|
||||||
|
definition_managed_entry_updates = {}
|
||||||
|
definitions_managed_entries
|
||||||
|
old_definition = {'dn': entry.dn, 'deleteentry': ['dn: %s' % entry.dn]}
|
||||||
|
old_template = entry.getValue('managedtemplate')
|
||||||
|
entry.setValues('managedtemplate', entry.getValue('managedtemplate').replace(old_template_container, sub[1] + new))
|
||||||
|
new_definition['dn'] = entry.dn.replace(old_definition_container, sub[0] + new)
|
||||||
|
new_definition['default'] = str(entry).strip().replace(': ', ':').split('\n')[1:]
|
||||||
|
definition_managed_entry_updates[new_definition['dn']] = new_definition
|
||||||
|
definition_managed_entry_updates[old_definition['dn']] = old_definition
|
||||||
|
old_templates.append(old_template)
|
||||||
|
new_managed_entries.append(definition_managed_entry_updates)
|
||||||
|
for old_template in old_templates:
|
||||||
|
try:
|
||||||
|
template = self.conn.getEntry(old_template, ldap.SCOPE_BASE, searchfilter,[])
|
||||||
|
new_template = {}
|
||||||
|
template_managed_entry_updates = {}
|
||||||
|
old_template = {'dn': template.dn, 'deleteentry': ['dn: %s' % template.dn]}
|
||||||
|
new_template['dn'] = template.dn.replace(old_template_container, sub[1] + new)
|
||||||
|
new_template['default'] = str(template).strip().replace(': ', ':').split('\n')[1:]
|
||||||
|
template_managed_entry_updates[new_template['dn']] = new_template
|
||||||
|
template_managed_entry_updates[old_template['dn']] = old_template
|
||||||
|
new_managed_entries.append(template_managed_entry_updates)
|
||||||
|
except errors.NotFound, e:
|
||||||
|
pass
|
||||||
|
if len(new_managed_entries) > 0:
|
||||||
|
new_managed_entries.sort(reverse=True)
|
||||||
|
|
||||||
|
return new_managed_entries
|
||||||
|
|
||||||
def __apply_updates(self, updates, entry):
|
def __apply_updates(self, updates, entry):
|
||||||
"""updates is a list of changes to apply
|
"""updates is a list of changes to apply
|
||||||
entry is the thing to apply them to
|
entry is the thing to apply them to
|
||||||
@ -431,7 +497,6 @@ class LDAPUpdate:
|
|||||||
for u in updates:
|
for u in updates:
|
||||||
# We already do syntax-parsing so this is safe
|
# We already do syntax-parsing so this is safe
|
||||||
(utype, k, values) = u.split(':',2)
|
(utype, k, values) = u.split(':',2)
|
||||||
|
|
||||||
values = self.__parse_values(values)
|
values = self.__parse_values(values)
|
||||||
|
|
||||||
e = entry.getValues(k)
|
e = entry.getValues(k)
|
||||||
@ -440,7 +505,6 @@ class LDAPUpdate:
|
|||||||
e = []
|
e = []
|
||||||
else:
|
else:
|
||||||
e = [e]
|
e = [e]
|
||||||
|
|
||||||
for v in values:
|
for v in values:
|
||||||
if utype == 'remove':
|
if utype == 'remove':
|
||||||
logging.debug("remove: '%s' from %s, current value %s", v, k, e)
|
logging.debug("remove: '%s' from %s, current value %s", v, k, e)
|
||||||
@ -629,6 +693,18 @@ class LDAPUpdate:
|
|||||||
and child in the wrong order.
|
and child in the wrong order.
|
||||||
"""
|
"""
|
||||||
dn = updates['dn']
|
dn = updates['dn']
|
||||||
|
deletes = updates.get('deleteentry', [])
|
||||||
|
for d in deletes:
|
||||||
|
try:
|
||||||
|
if self.live_run:
|
||||||
|
self.conn.deleteEntry(dn)
|
||||||
|
self.modified = True
|
||||||
|
except errors.NotFound, e:
|
||||||
|
logging.info("Deleting non-existent entry %s", e)
|
||||||
|
self.modified = True
|
||||||
|
except errors.DatabaseError, e:
|
||||||
|
logging.error("Delete failed: %s", e)
|
||||||
|
|
||||||
updates = updates.get('updates', [])
|
updates = updates.get('updates', [])
|
||||||
for u in updates:
|
for u in updates:
|
||||||
# We already do syntax-parsing so this is safe
|
# We already do syntax-parsing so this is safe
|
||||||
@ -659,13 +735,7 @@ class LDAPUpdate:
|
|||||||
f.sort()
|
f.sort()
|
||||||
return f
|
return f
|
||||||
|
|
||||||
def update(self, files):
|
def create_connection(self):
|
||||||
"""Execute the update. files is a list of the update files to use.
|
|
||||||
|
|
||||||
returns True if anything was changed, otherwise False
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
if self.online:
|
if self.online:
|
||||||
if self.ldapi:
|
if self.ldapi:
|
||||||
self.conn = ipaldap.IPAdmin(ldapi=True, realm=self.realm)
|
self.conn = ipaldap.IPAdmin(ldapi=True, realm=self.realm)
|
||||||
@ -689,6 +759,15 @@ class LDAPUpdate:
|
|||||||
raise RuntimeError('%s' % e.args[0].get('info', '').strip())
|
raise RuntimeError('%s' % e.args[0].get('info', '').strip())
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Offline updates are not supported.")
|
raise RuntimeError("Offline updates are not supported.")
|
||||||
|
|
||||||
|
def update(self, files):
|
||||||
|
"""Execute the update. files is a list of the update files to use.
|
||||||
|
|
||||||
|
returns True if anything was changed, otherwise False
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.create_connection()
|
||||||
all_updates = {}
|
all_updates = {}
|
||||||
dn_list = {}
|
dn_list = {}
|
||||||
for f in files:
|
for f in files:
|
||||||
@ -701,6 +780,20 @@ class LDAPUpdate:
|
|||||||
|
|
||||||
(all_updates, dn_list) = self.parse_update_file(data, all_updates, dn_list)
|
(all_updates, dn_list) = self.parse_update_file(data, all_updates, dn_list)
|
||||||
|
|
||||||
|
# Process Managed Entry Updates
|
||||||
|
managed_entries = self.__update_managed_entries()
|
||||||
|
if managed_entries:
|
||||||
|
managed_entry_dns = [[m[entry]['dn'] for entry in m] for m in managed_entries]
|
||||||
|
l = len(dn_list.keys())
|
||||||
|
|
||||||
|
# Add Managed Entry DN's to the DN List
|
||||||
|
for dn in managed_entry_dns:
|
||||||
|
l+=1
|
||||||
|
dn_list[l] = dn
|
||||||
|
# Add Managed Entry Updates to All Updates List
|
||||||
|
for managed_entry in managed_entries:
|
||||||
|
all_updates.update(managed_entry)
|
||||||
|
|
||||||
# For adds and updates we want to apply updates from shortest
|
# For adds and updates we want to apply updates from shortest
|
||||||
# to greatest length of the DN. For deletes we want the reverse.
|
# to greatest length of the DN. For deletes we want the reverse.
|
||||||
sortedkeys = dn_list.keys()
|
sortedkeys = dn_list.keys()
|
||||||
@ -709,6 +802,13 @@ class LDAPUpdate:
|
|||||||
for dn in dn_list[k]:
|
for dn in dn_list[k]:
|
||||||
self.__update_record(all_updates[dn])
|
self.__update_record(all_updates[dn])
|
||||||
|
|
||||||
|
# Restart 389 Directory Service
|
||||||
|
socket_name = '/var/run/slapd-%s.socket' % self.realm.replace('.','-')
|
||||||
|
iparestart = IPARestart()
|
||||||
|
iparestart.create_instance()
|
||||||
|
installutils.wait_for_open_socket(socket_name)
|
||||||
|
self.create_connection()
|
||||||
|
|
||||||
sortedkeys.reverse()
|
sortedkeys.reverse()
|
||||||
for k in sortedkeys:
|
for k in sortedkeys:
|
||||||
for dn in dn_list[k]:
|
for dn in dn_list[k]:
|
||||||
|
Loading…
Reference in New Issue
Block a user