mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-28 01:41:14 -06:00
23507e6124
The six way of doing this is to replace all occurences of "unicode" with "six.text_type". However, "unicode" is non-ambiguous and (arguably) easier to read. Also, using it makes the patches smaller, which should help with backporting. Reviewed-By: Petr Viktorin <pviktori@redhat.com>
178 lines
6.2 KiB
Python
178 lines
6.2 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/>.
|
|
|
|
import six
|
|
|
|
from ipalib import api, errors
|
|
from ipalib import Updater
|
|
from ipapython import ipautil
|
|
from ipapython.dn import DN
|
|
|
|
if six.PY3:
|
|
unicode = str
|
|
|
|
|
|
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 item in entry[attr]:
|
|
update.append(dict(attr=str(attr), value=str(item)))
|
|
else:
|
|
update.append(dict(attr=str(attr), value=str(entry[attr])))
|
|
|
|
return update
|
|
|
|
|
|
class GenerateUpdateMixin(object):
|
|
def _dn_suffix_replace(self, dn, old_suffix, new_suffix):
|
|
"""Replace all occurences of "old" AVAs in a DN by "new"
|
|
|
|
If the input DN doesn't end with old_suffix, log, an raise ValueError.
|
|
"""
|
|
if not dn.endswith(old_suffix):
|
|
self.error("unable to replace suffix '%s' with '%s' in '%s'",
|
|
old_suffix, new_suffix, dn)
|
|
raise ValueError('no replacement made')
|
|
return DN(*dn[:-len(old_suffix)]) + new_suffix
|
|
|
|
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.api.Backend.ldap2
|
|
|
|
suffix = ipautil.realm_to_suffix(self.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 as 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 as e:
|
|
pass
|
|
else:
|
|
# Compute the new dn by replacing the old container with the new container
|
|
try:
|
|
new_dn = self._dn_suffix_replace(
|
|
entry.dn,
|
|
old_suffix=old_template_container,
|
|
new_suffix=new_template_container)
|
|
except ValueError:
|
|
continue
|
|
|
|
# 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(old_update)
|
|
update_list.append(new_update)
|
|
|
|
else:
|
|
# Update the template dn by replacing the old containter with the new container
|
|
try:
|
|
new_dn = self._dn_suffix_replace(
|
|
entry['managedtemplate'][0],
|
|
old_suffix=old_template_container,
|
|
new_suffix=new_template_container)
|
|
except ValueError:
|
|
continue
|
|
entry['managedtemplate'] = new_dn
|
|
|
|
# Update the entry dn similarly
|
|
try:
|
|
new_dn = self._dn_suffix_replace(
|
|
entry.dn,
|
|
old_suffix=old_definition_container,
|
|
new_suffix=new_definition_container)
|
|
except ValueError:
|
|
continue
|
|
|
|
# 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_update)
|
|
|
|
if len(update_list) > 0:
|
|
restart = True
|
|
update_list.sort(reverse=True, key=lambda x: x['dn'])
|
|
|
|
return (restart, update_list)
|
|
|
|
class update_managed_post_first(Updater, GenerateUpdateMixin):
|
|
"""
|
|
Update managed entries
|
|
"""
|
|
|
|
def execute(self, **options):
|
|
# Never need to restart with the pre-update changes
|
|
(ignore, update_list) = self.generate_update(False)
|
|
|
|
return False, update_list
|
|
|
|
api.register(update_managed_post_first)
|
|
|
|
class update_managed_post(Updater, GenerateUpdateMixin):
|
|
"""
|
|
Update managed entries
|
|
"""
|
|
|
|
def execute(self, **options):
|
|
(restart, update_list) = self.generate_update(True)
|
|
|
|
return restart, update_list
|
|
|
|
api.register(update_managed_post)
|