mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-28 01:41:14 -06:00
162 lines
6.1 KiB
Python
162 lines
6.1 KiB
Python
# Authors:
|
|
# Rob Crittenden <rcritten@redhat.com>
|
|
#
|
|
# Copyright (C) 2011 Red Hat
|
|
# see file 'COPYING' for use and warranty information
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
from ipaserver.install.plugins import FIRST, LAST
|
|
from ipaserver.install.plugins.baseupdate import PreUpdate, PostUpdate
|
|
from ipalib import api, errors
|
|
from ipapython import ipautil
|
|
from ipapython.dn import DN, EditableDN
|
|
|
|
def entry_to_update(entry):
|
|
"""
|
|
Convert an entry into a name/value pair list that looks like an update.
|
|
|
|
An entry is a dict.
|
|
|
|
An update is a list of name/value pairs.
|
|
"""
|
|
update = []
|
|
for attr in entry.keys():
|
|
if isinstance(entry[attr], list):
|
|
for i in xrange(len(entry[attr])):
|
|
update.append('%s:%s' % (str(attr), str(entry[attr][i])))
|
|
else:
|
|
update.append('%s:%s' % (str(attr), str(entry[attr])))
|
|
|
|
return update
|
|
|
|
class GenerateUpdateMixin(object):
|
|
def generate_update(self, deletes=False):
|
|
"""
|
|
We need to separate the deletes that need to happen from the
|
|
new entries that need to be added.
|
|
"""
|
|
ldap = self.obj.backend
|
|
|
|
suffix = ipautil.realm_to_suffix(api.env.realm)
|
|
searchfilter = '(objectclass=*)'
|
|
definitions_managed_entries = []
|
|
|
|
old_template_container = DN(('cn', 'etc'), suffix)
|
|
new_template_container = DN(('cn', 'Templates'), ('cn', 'Managed Entries'), ('cn', 'etc'), suffix)
|
|
|
|
old_definition_container = DN(('cn', 'managed entries'), ('cn', 'plugins'), ('cn', 'config'), suffix)
|
|
new_definition_container = DN(('cn', 'Definitions'), ('cn', 'Managed Entries'), ('cn', 'etc'), suffix)
|
|
|
|
definitions_dn = DN(('cn', 'Definitions'))
|
|
update_list = []
|
|
restart = False
|
|
|
|
# If the old entries don't exist the server has already been updated.
|
|
try:
|
|
definitions_managed_entries, truncated = ldap.find_entries(
|
|
searchfilter, ['*'], old_definition_container,
|
|
ldap.SCOPE_ONELEVEL)
|
|
except errors.NotFound, e:
|
|
return (False, update_list)
|
|
|
|
for entry in definitions_managed_entries:
|
|
assert isinstance(entry.dn, DN)
|
|
if deletes:
|
|
old_dn = entry['managedtemplate'][0]
|
|
assert isinstance(old_dn, DN)
|
|
try:
|
|
entry = ldap.get_entry(old_dn, ['*'])
|
|
except errors.NotFound, e:
|
|
pass
|
|
else:
|
|
# Compute the new dn by replacing the old container with the new container
|
|
new_dn = EditableDN(entry.dn)
|
|
if new_dn.replace(old_template_container, new_template_container) != 1:
|
|
self.error("unable to replace '%s' with '%s' in '%s'",
|
|
old_template_container, new_template_container, entry.dn)
|
|
continue
|
|
|
|
new_dn = DN(new_dn)
|
|
|
|
# The old attributes become defaults for the new entry
|
|
new_update = {'dn': new_dn,
|
|
'default': entry_to_update(entry)}
|
|
|
|
# Delete the old entry
|
|
old_update = {'dn': entry.dn, 'deleteentry': None}
|
|
|
|
# Add the delete and replacement updates to the list of all updates
|
|
update_list.append({entry.dn: old_update, new_dn: new_update})
|
|
|
|
else:
|
|
# Update the template dn by replacing the old containter with the new container
|
|
old_dn = entry['managedtemplate'][0]
|
|
new_dn = EditableDN(old_dn)
|
|
if new_dn.replace(old_template_container, new_template_container) != 1:
|
|
self.error("unable to replace '%s' with '%s' in '%s'",
|
|
old_template_container, new_template_container, old_dn)
|
|
continue
|
|
new_dn = DN(new_dn)
|
|
entry['managedtemplate'] = new_dn
|
|
|
|
# Edit the dn, then convert it back to an immutable DN
|
|
old_dn = entry.dn
|
|
new_dn = EditableDN(old_dn)
|
|
if new_dn.replace(old_definition_container, new_definition_container) != 1:
|
|
self.error("unable to replace '%s' with '%s' in '%s'",
|
|
old_definition_container, new_definition_container, old_dn)
|
|
continue
|
|
new_dn = DN(new_dn)
|
|
|
|
# The old attributes become defaults for the new entry
|
|
new_update = {'dn': new_dn,
|
|
'default': entry_to_update(entry)}
|
|
|
|
# Add the replacement update to the collection of all updates
|
|
update_list.append({new_dn: new_update})
|
|
|
|
if len(update_list) > 0:
|
|
restart = True
|
|
update_list.sort(reverse=True)
|
|
|
|
return (restart, update_list)
|
|
|
|
class update_managed_post_first(PreUpdate, GenerateUpdateMixin):
|
|
"""
|
|
Update managed entries
|
|
"""
|
|
order=FIRST
|
|
|
|
def execute(self, **options):
|
|
# Never need to restart with the pre-update changes
|
|
(ignore, update_list) = self.generate_update(False)
|
|
|
|
return (False, True, update_list)
|
|
|
|
api.register(update_managed_post_first)
|
|
|
|
class update_managed_post(PostUpdate, GenerateUpdateMixin):
|
|
"""
|
|
Update managed entries
|
|
"""
|
|
order=LAST
|
|
|
|
def execute(self, **options):
|
|
(restart, update_list) = self.generate_update(True)
|
|
|
|
return (restart, True, update_list)
|
|
|
|
api.register(update_managed_post)
|