mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Server Upgrade: specify order of plugins in update files
* add 'plugin' directive * specify plugins order in update files * remove 'run plugins' options * use ldapupdater API instance in plugins * add update files representing former PreUpdate and PostUpdate order of plugins https://fedorahosted.org/freeipa/ticket/4904 Reviewed-By: David Kupka <dkupka@redhat.com>
This commit is contained in:
parent
cc19b5a76a
commit
f24f614396
@ -69,7 +69,11 @@ A few rules:
|
|||||||
6. If a DN does exist the default values are skipped
|
6. If a DN does exist the default values are skipped
|
||||||
7. Only the first rule on a line is respected
|
7. Only the first rule on a line is respected
|
||||||
|
|
||||||
Adds and updates are applied from shortest to longest length of DN. Deletes are done from longest to shortest.
|
ipa-ldap-updater allows to execute update plugins.
|
||||||
|
Plugins to be executed are specified with following keyword, in update files:
|
||||||
|
* plugin: name of plugin
|
||||||
|
|
||||||
|
This keyword is not bounded to DN, and plugin names have to be registered in API.
|
||||||
|
|
||||||
Additionally, ipa-ldap-updater can update the schema based on LDIF files.
|
Additionally, ipa-ldap-updater can update the schema based on LDIF files.
|
||||||
Any missing object classes and attribute types are added, and differing ones are updated to match the LDIF file.
|
Any missing object classes and attribute types are added, and differing ones are updated to match the LDIF file.
|
||||||
@ -81,11 +85,8 @@ Schema files should be in LDIF format, and may only specify attributeTypes and o
|
|||||||
\fB\-d\fR, \fB\-\-debug\fR
|
\fB\-d\fR, \fB\-\-debug\fR
|
||||||
Enable debug logging when more verbose output is needed
|
Enable debug logging when more verbose output is needed
|
||||||
.TP
|
.TP
|
||||||
\fB\-p\fR, \fB\-\-plugins\fR
|
|
||||||
Execute update plugins as well as any update files. There is no way to execute only the plugins.
|
|
||||||
.TP
|
|
||||||
\fB\-u\fR, \fB\-\-upgrade\fR
|
\fB\-u\fR, \fB\-\-upgrade\fR
|
||||||
Upgrade an installed server in offline mode (implies \-\-ldapi, \-\-plugins, and \-\-schema)
|
Upgrade an installed server in offline mode (implies \-\-schema)
|
||||||
.TP
|
.TP
|
||||||
\fB\-s\fR, \fB\-\-schema\fR
|
\fB\-s\fR, \fB\-\-schema\fR
|
||||||
Also update the LDAP schema. If no \-\-schema-file is specified, update to the built-in IPA schema.
|
Also update the LDAP schema. If no \-\-schema-file is specified, update to the built-in IPA schema.
|
||||||
|
10
install/updates/05-pre_upgrade_plugins.update
Normal file
10
install/updates/05-pre_upgrade_plugins.update
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# first
|
||||||
|
plugin: update_managed_post_first
|
||||||
|
|
||||||
|
# middle
|
||||||
|
plugin: update_replica_attribute_lists
|
||||||
|
plugin: update_passync_privilege_check
|
||||||
|
plugin: update_referint
|
||||||
|
plugin: update_uniqueness_plugins_to_new_syntax
|
||||||
|
|
||||||
|
# last
|
20
install/updates/90-post_upgrade_plugins.update
Normal file
20
install/updates/90-post_upgrade_plugins.update
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# first
|
||||||
|
|
||||||
|
|
||||||
|
# middle
|
||||||
|
plugin: update_dnszones
|
||||||
|
plugin: update_dns_limits
|
||||||
|
plugin: update_default_range
|
||||||
|
plugin: update_default_trust_view
|
||||||
|
plugin: update_ca_renewal_master
|
||||||
|
plugin: update_idrange_type
|
||||||
|
plugin: update_pacs
|
||||||
|
plugin: update_service_principalalias
|
||||||
|
plugin: update_upload_cacrt
|
||||||
|
|
||||||
|
# last
|
||||||
|
plugin: update_master_to_dnsforwardzones
|
||||||
|
plugin: update_managed_post
|
||||||
|
plugin: update_managed_permissions
|
||||||
|
plugin: update_idrange_baserid
|
||||||
|
plugin: update_passync_privilege_update
|
@ -2,6 +2,7 @@ NULL =
|
|||||||
|
|
||||||
appdir = $(IPA_DATA_DIR)/updates
|
appdir = $(IPA_DATA_DIR)/updates
|
||||||
app_DATA = \
|
app_DATA = \
|
||||||
|
05-pre_upgrade_plugins.update \
|
||||||
10-config.update \
|
10-config.update \
|
||||||
10-enable-betxn.update \
|
10-enable-betxn.update \
|
||||||
10-selinuxusermap.update \
|
10-selinuxusermap.update \
|
||||||
@ -47,6 +48,7 @@ app_DATA = \
|
|||||||
61-trusts-s4u2proxy.update \
|
61-trusts-s4u2proxy.update \
|
||||||
62-ranges.update \
|
62-ranges.update \
|
||||||
71-idviews.update \
|
71-idviews.update \
|
||||||
|
90-post_upgrade_plugins.update \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
@ -1371,7 +1371,7 @@ class Method(Attribute, Command):
|
|||||||
|
|
||||||
|
|
||||||
@register.base()
|
@register.base()
|
||||||
class Updater(Method):
|
class Updater(Plugin):
|
||||||
"""
|
"""
|
||||||
An LDAP update with an associated object (always update).
|
An LDAP update with an associated object (always update).
|
||||||
|
|
||||||
@ -1397,8 +1397,8 @@ class Updater(Method):
|
|||||||
>>> api.Updater.my_update # doctest:+ELLIPSIS
|
>>> api.Updater.my_update # doctest:+ELLIPSIS
|
||||||
ipalib.frontend.my_update()
|
ipalib.frontend.my_update()
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def execute(self, **options):
|
||||||
super(Updater, self).__init__()
|
raise NotImplementedError('%s.execute()' % self.name)
|
||||||
|
|
||||||
def __call__(self, **options):
|
def __call__(self, **options):
|
||||||
self.debug(
|
self.debug(
|
||||||
|
@ -507,7 +507,8 @@ class DsInstance(service.Service):
|
|||||||
conn.unbind()
|
conn.unbind()
|
||||||
|
|
||||||
def apply_updates(self):
|
def apply_updates(self):
|
||||||
ld = ldapupdate.LDAPUpdate(dm_password=self.dm_password, sub_dict=self.sub_dict, plugins=True)
|
ld = ldapupdate.LDAPUpdate(dm_password=self.dm_password,
|
||||||
|
sub_dict=self.sub_dict)
|
||||||
files = ld.get_all_files(ldapupdate.UPDATES_DIR)
|
files = ld.get_all_files(ldapupdate.UPDATES_DIR)
|
||||||
ld.update(files)
|
ld.update(files)
|
||||||
|
|
||||||
|
@ -48,10 +48,6 @@ class LDAPUpdater(admintool.AdminTool):
|
|||||||
parser.add_option("-u", '--upgrade', action="store_true",
|
parser.add_option("-u", '--upgrade', action="store_true",
|
||||||
dest="upgrade", default=False,
|
dest="upgrade", default=False,
|
||||||
help="upgrade an installed server in offline mode")
|
help="upgrade an installed server in offline mode")
|
||||||
parser.add_option("-p", '--plugins', action="store_true",
|
|
||||||
dest="plugins", default=False,
|
|
||||||
help="execute update plugins " +
|
|
||||||
"(implied when no input files are given)")
|
|
||||||
parser.add_option("-s", '--schema', action="store_true",
|
parser.add_option("-s", '--schema', action="store_true",
|
||||||
dest="update_schema", default=False,
|
dest="update_schema", default=False,
|
||||||
help="update the schema "
|
help="update the schema "
|
||||||
@ -140,10 +136,6 @@ class LDAPUpdater_NonUpgrade(LDAPUpdater):
|
|||||||
|
|
||||||
def validate_options(self):
|
def validate_options(self):
|
||||||
super(LDAPUpdater_NonUpgrade, self).validate_options()
|
super(LDAPUpdater_NonUpgrade, self).validate_options()
|
||||||
options = self.options
|
|
||||||
|
|
||||||
# Only run plugins if no files are given
|
|
||||||
self.run_plugins = not self.files or options.plugins
|
|
||||||
|
|
||||||
# Need root for running plugins
|
# Need root for running plugins
|
||||||
if os.getegid() != 0:
|
if os.getegid() != 0:
|
||||||
@ -167,8 +159,7 @@ class LDAPUpdater_NonUpgrade(LDAPUpdater):
|
|||||||
|
|
||||||
ld = LDAPUpdate(
|
ld = LDAPUpdate(
|
||||||
sub_dict={},
|
sub_dict={},
|
||||||
ldapi=True,
|
ldapi=True)
|
||||||
plugins=options.plugins or self.run_plugins)
|
|
||||||
|
|
||||||
if not self.files:
|
if not self.files:
|
||||||
self.files = ld.get_all_files(UPDATES_DIR)
|
self.files = ld.get_all_files(UPDATES_DIR)
|
||||||
|
@ -36,13 +36,14 @@ import krbV
|
|||||||
import ldap
|
import ldap
|
||||||
|
|
||||||
from ipaserver.install import installutils
|
from ipaserver.install import installutils
|
||||||
|
from ipaserver.install.plugins.baseupdate import DSRestart
|
||||||
from ipapython import ipautil, ipaldap
|
from ipapython import ipautil, ipaldap
|
||||||
from ipalib import errors
|
from ipalib import errors
|
||||||
from ipalib import api
|
from ipalib import api, create_api
|
||||||
from ipaplatform.paths import paths
|
from ipaplatform.paths import paths
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import *
|
from ipapython.ipa_log_manager import *
|
||||||
from ipaserver.install.plugins import (PRE_UPDATE, POST_UPDATE)
|
from ipapython.ipautil import wait_for_open_socket
|
||||||
from ipaserver.plugins import ldap2
|
from ipaserver.plugins import ldap2
|
||||||
|
|
||||||
UPDATES_DIR=paths.UPDATES_DIR
|
UPDATES_DIR=paths.UPDATES_DIR
|
||||||
@ -113,7 +114,7 @@ class LDAPUpdate:
|
|||||||
action_keywords = ["default", "add", "remove", "only", "onlyifexist", "deleteentry", "replace", "addifnew", "addifexist"]
|
action_keywords = ["default", "add", "remove", "only", "onlyifexist", "deleteentry", "replace", "addifnew", "addifexist"]
|
||||||
|
|
||||||
def __init__(self, dm_password=None, sub_dict={},
|
def __init__(self, dm_password=None, sub_dict={},
|
||||||
online=True, ldapi=False, plugins=False):
|
online=True, ldapi=False):
|
||||||
'''
|
'''
|
||||||
:parameters:
|
:parameters:
|
||||||
dm_password
|
dm_password
|
||||||
@ -124,8 +125,6 @@ class LDAPUpdate:
|
|||||||
Do an online LDAP update or use an experimental LDIF updater
|
Do an online LDAP update or use an experimental LDIF updater
|
||||||
ldapi
|
ldapi
|
||||||
Bind using ldapi. This assumes autobind is enabled.
|
Bind using ldapi. This assumes autobind is enabled.
|
||||||
plugins
|
|
||||||
execute the pre/post update plugins
|
|
||||||
|
|
||||||
Data Structure Example:
|
Data Structure Example:
|
||||||
-----------------------
|
-----------------------
|
||||||
@ -152,6 +151,67 @@ class LDAPUpdate:
|
|||||||
|
|
||||||
The default and update lists are "dispositions"
|
The default and update lists are "dispositions"
|
||||||
|
|
||||||
|
Plugins:
|
||||||
|
|
||||||
|
Plugins has to be specified in update file to be executed, using
|
||||||
|
'plugin' directive
|
||||||
|
|
||||||
|
Example:
|
||||||
|
plugin: update_uniqueness_plugins_to_new_syntax
|
||||||
|
|
||||||
|
Each plugin returns two values:
|
||||||
|
|
||||||
|
1. restart: dirsrv will be restarted AFTER this update is
|
||||||
|
applied.
|
||||||
|
2. updates: A list of updates to be applied.
|
||||||
|
|
||||||
|
The value of an update is a dictionary with the following possible
|
||||||
|
values:
|
||||||
|
- dn: DN, equal to the dn attribute
|
||||||
|
- updates: list of updates against the dn
|
||||||
|
- default: list of the default entry to be added if it doesn't
|
||||||
|
exist
|
||||||
|
- deleteentry: list of dn's to be deleted (typically single dn)
|
||||||
|
|
||||||
|
For example, this update file:
|
||||||
|
|
||||||
|
dn: cn=global_policy,cn=$REALM,cn=kerberos,$SUFFIX
|
||||||
|
replace:krbPwdLockoutDuration:10::600
|
||||||
|
replace: krbPwdMaxFailure:3::6
|
||||||
|
|
||||||
|
Generates this list which contain the update dictionary:
|
||||||
|
|
||||||
|
[
|
||||||
|
dict(
|
||||||
|
'dn': 'cn=global_policy,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com',
|
||||||
|
'updates': ['replace:krbPwdLockoutDuration:10::600',
|
||||||
|
'replace:krbPwdMaxFailure:3::6']
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
Here is another example showing how a default entry is configured:
|
||||||
|
|
||||||
|
dn: cn=Managed Entries,cn=etc,$SUFFIX
|
||||||
|
default: objectClass: nsContainer
|
||||||
|
default: objectClass: top
|
||||||
|
default: cn: Managed Entries
|
||||||
|
|
||||||
|
This generates:
|
||||||
|
|
||||||
|
[
|
||||||
|
dict(
|
||||||
|
'dn': 'cn=Managed Entries,cn=etc,dc=example,dc=com',
|
||||||
|
'default': ['objectClass:nsContainer',
|
||||||
|
'objectClass:top',
|
||||||
|
'cn:Managed Entries'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
Note that the variable substitution in both examples has been completed.
|
||||||
|
|
||||||
|
Either may make changes directly in LDAP or can return updates in
|
||||||
|
update format.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
log_mgr.get_logger(self, True)
|
log_mgr.get_logger(self, True)
|
||||||
@ -161,9 +221,15 @@ class LDAPUpdate:
|
|||||||
self.modified = False
|
self.modified = False
|
||||||
self.online = online
|
self.online = online
|
||||||
self.ldapi = ldapi
|
self.ldapi = ldapi
|
||||||
self.plugins = plugins
|
|
||||||
self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
|
self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
|
||||||
self.realm = None
|
self.realm = None
|
||||||
|
self.socket_name = (
|
||||||
|
paths.SLAPD_INSTANCE_SOCKET_TEMPLATE %
|
||||||
|
api.env.realm.replace('.', '-')
|
||||||
|
)
|
||||||
|
self.ldapuri = 'ldapi://%s' % ipautil.format_netloc(
|
||||||
|
self.socket_name
|
||||||
|
)
|
||||||
suffix = None
|
suffix = None
|
||||||
|
|
||||||
if sub_dict.get("REALM"):
|
if sub_dict.get("REALM"):
|
||||||
@ -202,13 +268,14 @@ class LDAPUpdate:
|
|||||||
self.sub_dict["TIME"] = int(time.time())
|
self.sub_dict["TIME"] = int(time.time())
|
||||||
if not self.sub_dict.get("DOMAIN") and domain is not None:
|
if not self.sub_dict.get("DOMAIN") and domain is not None:
|
||||||
self.sub_dict["DOMAIN"] = domain
|
self.sub_dict["DOMAIN"] = domain
|
||||||
|
self.api = create_api(mode=None)
|
||||||
|
self.api.bootstrap(in_server=True, context='updates')
|
||||||
|
self.api.finalize()
|
||||||
if online:
|
if online:
|
||||||
# Try out the connection/password
|
# Try out the connection/password
|
||||||
# (This will raise if the server is not available)
|
# (This will raise if the server is not available)
|
||||||
self.create_connection()
|
self.create_connection()
|
||||||
self.conn.unbind()
|
self.close_connection()
|
||||||
self.conn = None
|
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Offline updates are not supported.")
|
raise RuntimeError("Offline updates are not supported.")
|
||||||
|
|
||||||
@ -333,6 +400,13 @@ class LDAPUpdate:
|
|||||||
assert isinstance(dn, DN)
|
assert isinstance(dn, DN)
|
||||||
all_updates.append(update)
|
all_updates.append(update)
|
||||||
|
|
||||||
|
def emit_plugin_update(update):
|
||||||
|
'''
|
||||||
|
When processing a plugin is complete emit the plugin update by
|
||||||
|
appending it into list of all updates
|
||||||
|
'''
|
||||||
|
all_updates.append(update)
|
||||||
|
|
||||||
# Iterate over source input lines
|
# Iterate over source input lines
|
||||||
for source_line in source_data:
|
for source_line in source_data:
|
||||||
lcount += 1
|
lcount += 1
|
||||||
@ -344,18 +418,38 @@ class LDAPUpdate:
|
|||||||
if source_line.startswith('#') or source_line == '':
|
if source_line.startswith('#') or source_line == '':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if source_line.lower().startswith('dn:'):
|
state = None
|
||||||
# Starting new dn
|
emit_previous_dn = False
|
||||||
if dn is not None:
|
|
||||||
# Emit previous dn
|
|
||||||
emit_item(logical_line)
|
|
||||||
logical_line = ''
|
|
||||||
emit_update(update)
|
|
||||||
update = {}
|
|
||||||
|
|
||||||
|
# parse special keywords
|
||||||
|
if source_line.lower().startswith('dn:'):
|
||||||
|
state = 'dn'
|
||||||
|
emit_previous_dn = True
|
||||||
|
elif source_line.lower().startswith('plugin:'):
|
||||||
|
state = 'plugin'
|
||||||
|
emit_previous_dn = True
|
||||||
|
|
||||||
|
if emit_previous_dn and dn is not None:
|
||||||
|
# Emit previous dn
|
||||||
|
emit_item(logical_line)
|
||||||
|
logical_line = ''
|
||||||
|
emit_update(update)
|
||||||
|
update = {}
|
||||||
|
dn = None
|
||||||
|
|
||||||
|
if state == 'dn':
|
||||||
|
# Starting new dn
|
||||||
dn = source_line[3:].strip()
|
dn = source_line[3:].strip()
|
||||||
dn = DN(self._template_str(dn))
|
dn = DN(self._template_str(dn))
|
||||||
update['dn'] = dn
|
update['dn'] = dn
|
||||||
|
elif state == 'plugin':
|
||||||
|
# plugin specification is online only
|
||||||
|
plugin_name = source_line[7:].strip()
|
||||||
|
if not plugin_name:
|
||||||
|
raise BadSyntax("plugin name is not defined")
|
||||||
|
update['plugin'] = plugin_name
|
||||||
|
emit_plugin_update(update)
|
||||||
|
update = {}
|
||||||
else:
|
else:
|
||||||
# Process items belonging to dn
|
# Process items belonging to dn
|
||||||
if dn is None:
|
if dn is None:
|
||||||
@ -589,10 +683,6 @@ class LDAPUpdate:
|
|||||||
def _update_record(self, update):
|
def _update_record(self, update):
|
||||||
found = False
|
found = False
|
||||||
|
|
||||||
# If the entry is going to be deleted no point in processing it.
|
|
||||||
if update.has_key('deleteentry'):
|
|
||||||
return
|
|
||||||
|
|
||||||
new_entry = self._create_default_entry(update.get('dn'),
|
new_entry = self._create_default_entry(update.get('dn'),
|
||||||
update.get('default'))
|
update.get('default'))
|
||||||
|
|
||||||
@ -687,9 +777,6 @@ class LDAPUpdate:
|
|||||||
and child in the wrong order.
|
and child in the wrong order.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not updates.has_key('deleteentry'):
|
|
||||||
return
|
|
||||||
|
|
||||||
dn = updates['dn']
|
dn = updates['dn']
|
||||||
try:
|
try:
|
||||||
self.info("Deleting entry %s", dn)
|
self.info("Deleting entry %s", dn)
|
||||||
@ -713,20 +800,36 @@ class LDAPUpdate:
|
|||||||
f.sort()
|
f.sort()
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
def _run_update_plugin(self, plugin_name):
|
||||||
|
self.log.info("Executing upgrade plugin: %s", plugin_name)
|
||||||
|
restart_ds, updates = self.api.Updater[plugin_name]()
|
||||||
|
if updates:
|
||||||
|
self._run_updates(updates)
|
||||||
|
# restart may be required even if no updates were returned
|
||||||
|
# from plugin, plugin may change LDAP data directly
|
||||||
|
if restart_ds:
|
||||||
|
self.close_connection()
|
||||||
|
self.restart_ds()
|
||||||
|
self.create_connection()
|
||||||
|
|
||||||
def create_connection(self):
|
def create_connection(self):
|
||||||
if self.online:
|
if self.online:
|
||||||
self.conn = connect(
|
self.api.Backend.ldap2.connect(
|
||||||
ldapi=self.ldapi, realm=self.realm, fqdn=self.sub_dict['FQDN'],
|
bind_dn=DN(('cn', 'Directory Manager')),
|
||||||
dm_password=self.dm_password, pw_name=self.pw_name)
|
bind_pw=self.dm_password,
|
||||||
|
autobind=self.ldapi)
|
||||||
|
self.conn = self.api.Backend.ldap2
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("Offline updates are not supported.")
|
raise RuntimeError("Offline updates are not supported.")
|
||||||
|
|
||||||
def _run_updates(self, all_updates):
|
def _run_updates(self, all_updates):
|
||||||
for update in all_updates:
|
for update in all_updates:
|
||||||
self._update_record(update)
|
if 'deleteentry' in update:
|
||||||
|
self._delete_record(update)
|
||||||
for update in all_updates:
|
elif 'plugin' in update:
|
||||||
self._delete_record(update)
|
self._run_update_plugin(update['plugin'])
|
||||||
|
else:
|
||||||
|
self._update_record(update)
|
||||||
|
|
||||||
def update(self, files, ordered=True):
|
def update(self, files, ordered=True):
|
||||||
"""Execute the update. files is a list of the update files to use.
|
"""Execute the update. files is a list of the update files to use.
|
||||||
@ -738,12 +841,6 @@ class LDAPUpdate:
|
|||||||
all_updates = []
|
all_updates = []
|
||||||
try:
|
try:
|
||||||
self.create_connection()
|
self.create_connection()
|
||||||
if self.plugins:
|
|
||||||
self.info('PRE_UPDATE')
|
|
||||||
updates = api.Backend.updateclient.update(
|
|
||||||
PRE_UPDATE, self.dm_password, self.ldapi)
|
|
||||||
# flush out PRE_UPDATE plugin updates before we begin
|
|
||||||
self._run_updates(updates)
|
|
||||||
|
|
||||||
upgrade_files = files
|
upgrade_files = files
|
||||||
if ordered:
|
if ordered:
|
||||||
@ -760,18 +857,11 @@ class LDAPUpdate:
|
|||||||
self.parse_update_file(f, data, all_updates)
|
self.parse_update_file(f, data, all_updates)
|
||||||
self._run_updates(all_updates)
|
self._run_updates(all_updates)
|
||||||
all_updates = []
|
all_updates = []
|
||||||
|
|
||||||
if self.plugins:
|
|
||||||
self.info('POST_UPDATE')
|
|
||||||
updates = api.Backend.updateclient.update(
|
|
||||||
POST_UPDATE, self.dm_password, self.ldapi)
|
|
||||||
self._run_updates(updates)
|
|
||||||
finally:
|
finally:
|
||||||
self.close_connection()
|
self.close_connection()
|
||||||
|
|
||||||
return self.modified
|
return self.modified
|
||||||
|
|
||||||
|
|
||||||
def update_from_dict(self, updates):
|
def update_from_dict(self, updates):
|
||||||
"""
|
"""
|
||||||
Apply updates internally as opposed to from a file.
|
Apply updates internally as opposed to from a file.
|
||||||
@ -788,5 +878,11 @@ class LDAPUpdate:
|
|||||||
def close_connection(self):
|
def close_connection(self):
|
||||||
"""Close ldap connection"""
|
"""Close ldap connection"""
|
||||||
if self.conn:
|
if self.conn:
|
||||||
self.conn.unbind()
|
self.api.Backend.ldap2.disconnect()
|
||||||
self.conn = None
|
self.conn = None
|
||||||
|
|
||||||
|
def restart_ds(self):
|
||||||
|
dsrestart = DSRestart()
|
||||||
|
|
||||||
|
dsrestart.create_instance()
|
||||||
|
wait_for_open_socket(self.socket_name)
|
||||||
|
@ -20,9 +20,3 @@
|
|||||||
"""
|
"""
|
||||||
Provide a separate api for updates.
|
Provide a separate api for updates.
|
||||||
"""
|
"""
|
||||||
PRE_UPDATE = 1
|
|
||||||
POST_UPDATE = 2
|
|
||||||
|
|
||||||
FIRST = 1
|
|
||||||
MIDDLE = 2
|
|
||||||
LAST = 4
|
|
||||||
|
@ -17,22 +17,20 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE
|
|
||||||
from ipaserver.install.plugins.baseupdate import PostUpdate
|
|
||||||
from ipalib import api, errors
|
from ipalib import api, errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import *
|
from ipapython.ipa_log_manager import *
|
||||||
|
|
||||||
DEFAULT_ID_RANGE_SIZE = 200000
|
DEFAULT_ID_RANGE_SIZE = 200000
|
||||||
|
|
||||||
class update_default_range(PostUpdate):
|
class update_default_range(Updater):
|
||||||
"""
|
"""
|
||||||
Create default ID range for upgraded servers.
|
Create default ID range for upgraded servers.
|
||||||
"""
|
"""
|
||||||
order=MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
dn = DN(api.env.container_ranges, api.env.basedn)
|
dn = DN(api.env.container_ranges, api.env.basedn)
|
||||||
search_filter = "objectclass=ipaDomainIDRange"
|
search_filter = "objectclass=ipaDomainIDRange"
|
||||||
@ -117,14 +115,13 @@ class update_default_range(PostUpdate):
|
|||||||
return False, [update]
|
return False, [update]
|
||||||
|
|
||||||
|
|
||||||
class update_default_trust_view(PostUpdate):
|
class update_default_trust_view(Updater):
|
||||||
"""
|
"""
|
||||||
Create Default Trust View for upgraded servers.
|
Create Default Trust View for upgraded servers.
|
||||||
"""
|
"""
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
default_trust_view_dn = DN(('cn', 'Default Trust View'),
|
default_trust_view_dn = DN(('cn', 'Default Trust View'),
|
||||||
api.env.container_views,
|
api.env.container_views,
|
||||||
|
@ -18,9 +18,8 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ipalib import api
|
from ipalib import api
|
||||||
from ipalib import Updater, Object
|
from ipalib import Object
|
||||||
from ipaserver.install import service
|
from ipaserver.install import service
|
||||||
from ipaserver.install.plugins import (PRE_UPDATE, POST_UPDATE, MIDDLE)
|
|
||||||
|
|
||||||
class DSRestart(service.Service):
|
class DSRestart(service.Service):
|
||||||
"""
|
"""
|
||||||
@ -46,32 +45,3 @@ class DSRestart(service.Service):
|
|||||||
self.step("starting directory server", self.start)
|
self.step("starting directory server", self.start)
|
||||||
self.start_creation(start_message="Restarting Directory server "
|
self.start_creation(start_message="Restarting Directory server "
|
||||||
"to apply updates", show_service_name=False)
|
"to apply updates", show_service_name=False)
|
||||||
|
|
||||||
class update(Object):
|
|
||||||
"""
|
|
||||||
Generic object used to register all updates into a single namespace.
|
|
||||||
"""
|
|
||||||
backend_name = 'ldap2'
|
|
||||||
|
|
||||||
api.register(update)
|
|
||||||
|
|
||||||
|
|
||||||
class PreUpdate(Updater):
|
|
||||||
"""
|
|
||||||
Base class for updates that run prior to file processing.
|
|
||||||
"""
|
|
||||||
updatetype = PRE_UPDATE
|
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(PreUpdate, self).__init__()
|
|
||||||
|
|
||||||
class PostUpdate(Updater):
|
|
||||||
"""
|
|
||||||
Base class for updates that run after file processing.
|
|
||||||
"""
|
|
||||||
updatetype = POST_UPDATE
|
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(PostUpdate, self).__init__()
|
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ipaserver.install.plugins.baseupdate import PostUpdate
|
|
||||||
from ipaserver.install import installutils, certs, cainstance
|
from ipaserver.install import installutils, certs, cainstance
|
||||||
from ipalib import errors
|
from ipalib import errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipalib.plugable import Registry
|
from ipalib.plugable import Registry
|
||||||
from ipapython import certmonger, dogtag
|
from ipapython import certmonger, dogtag
|
||||||
from ipaplatform.paths import paths
|
from ipaplatform.paths import paths
|
||||||
@ -28,7 +28,7 @@ from ipapython.dn import DN
|
|||||||
register = Registry()
|
register = Registry()
|
||||||
|
|
||||||
@register()
|
@register()
|
||||||
class update_ca_renewal_master(PostUpdate):
|
class update_ca_renewal_master(Updater):
|
||||||
"""
|
"""
|
||||||
Set CA renewal master in LDAP.
|
Set CA renewal master in LDAP.
|
||||||
"""
|
"""
|
||||||
@ -39,7 +39,7 @@ class update_ca_renewal_master(PostUpdate):
|
|||||||
self.debug("CA is not configured on this host")
|
self.debug("CA is not configured on this host")
|
||||||
return False, []
|
return False, []
|
||||||
|
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
|
base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
|
||||||
self.api.env.basedn)
|
self.api.env.basedn)
|
||||||
filter = '(&(cn=CA)(ipaConfigString=caRenewalMaster))'
|
filter = '(&(cn=CA)(ipaConfigString=caRenewalMaster))'
|
||||||
|
@ -24,16 +24,14 @@ import time
|
|||||||
|
|
||||||
from ldif import LDIFWriter
|
from ldif import LDIFWriter
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE, LAST
|
|
||||||
from ipaserver.install.plugins.baseupdate import (PostUpdate, PreUpdate)
|
|
||||||
from ipaserver.install import sysupgrade
|
|
||||||
from ipalib import api, errors, util
|
from ipalib import api, errors, util
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipalib.plugins.dns import dns_container_exists
|
from ipalib.plugins.dns import dns_container_exists
|
||||||
from ipapython.ipa_log_manager import *
|
from ipapython.ipa_log_manager import *
|
||||||
|
|
||||||
|
|
||||||
class update_dnszones(PostUpdate):
|
class update_dnszones(Updater):
|
||||||
"""
|
"""
|
||||||
Update all zones to meet requirements in the new FreeIPA versions
|
Update all zones to meet requirements in the new FreeIPA versions
|
||||||
|
|
||||||
@ -57,10 +55,9 @@ class update_dnszones(PostUpdate):
|
|||||||
|
|
||||||
This module extends the original policy to allow the SSHFP updates.
|
This module extends the original policy to allow the SSHFP updates.
|
||||||
"""
|
"""
|
||||||
order=MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
if not dns_container_exists(ldap):
|
if not dns_container_exists(ldap):
|
||||||
return False, []
|
return False, []
|
||||||
|
|
||||||
@ -95,7 +92,7 @@ class update_dnszones(PostUpdate):
|
|||||||
api.register(update_dnszones)
|
api.register(update_dnszones)
|
||||||
|
|
||||||
|
|
||||||
class update_dns_limits(PostUpdate):
|
class update_dns_limits(Updater):
|
||||||
"""
|
"""
|
||||||
bind-dyndb-ldap persistent search queries LDAP for all DNS records.
|
bind-dyndb-ldap persistent search queries LDAP for all DNS records.
|
||||||
The LDAP connection must have no size or time limits to work
|
The LDAP connection must have no size or time limits to work
|
||||||
@ -106,7 +103,7 @@ class update_dns_limits(PostUpdate):
|
|||||||
limit_value = '-1'
|
limit_value = '-1'
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
if not dns_container_exists(ldap):
|
if not dns_container_exists(ldap):
|
||||||
return False, []
|
return False, []
|
||||||
@ -142,7 +139,7 @@ class update_dns_limits(PostUpdate):
|
|||||||
api.register(update_dns_limits)
|
api.register(update_dns_limits)
|
||||||
|
|
||||||
|
|
||||||
class update_master_to_dnsforwardzones(PostUpdate):
|
class update_master_to_dnsforwardzones(Updater):
|
||||||
"""
|
"""
|
||||||
Update all zones to meet requirements in the new FreeIPA versions
|
Update all zones to meet requirements in the new FreeIPA versions
|
||||||
|
|
||||||
@ -152,14 +149,12 @@ class update_master_to_dnsforwardzones(PostUpdate):
|
|||||||
|
|
||||||
This should be applied only once, and only if original version was lower than 4.0
|
This should be applied only once, and only if original version was lower than 4.0
|
||||||
"""
|
"""
|
||||||
order = LAST
|
|
||||||
|
|
||||||
backup_dir = u'/var/lib/ipa/backup/'
|
backup_dir = u'/var/lib/ipa/backup/'
|
||||||
backup_filename = u'dns-forward-zones-backup-%Y-%m-%d-%H-%M-%S.ldif'
|
backup_filename = u'dns-forward-zones-backup-%Y-%m-%d-%H-%M-%S.ldif'
|
||||||
backup_path = u'%s%s' % (backup_dir, backup_filename)
|
backup_path = u'%s%s' % (backup_dir, backup_filename)
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
# check LDAP if forwardzones already uses new semantics
|
# check LDAP if forwardzones already uses new semantics
|
||||||
dns_container_dn = DN(api.env.container_dns, api.env.basedn)
|
dns_container_dn = DN(api.env.container_dns, api.env.basedn)
|
||||||
try:
|
try:
|
||||||
|
@ -20,23 +20,20 @@
|
|||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
from ipapython import ipaldap
|
from ipapython import ipaldap
|
||||||
from ipaserver.install.plugins import MIDDLE
|
|
||||||
from ipaserver.install.plugins.baseupdate import PreUpdate
|
|
||||||
from ipaserver.install import replication
|
from ipaserver.install import replication
|
||||||
from ipalib import api
|
from ipalib import api
|
||||||
|
from ipalib import Updater
|
||||||
|
|
||||||
EXCLUDE_TEMPLATE = '(objectclass=*) $ EXCLUDE %s'
|
EXCLUDE_TEMPLATE = '(objectclass=*) $ EXCLUDE %s'
|
||||||
|
|
||||||
|
|
||||||
class update_replica_attribute_lists(PreUpdate):
|
class update_replica_attribute_lists(Updater):
|
||||||
"""
|
"""
|
||||||
Run through all replication agreements and ensure that EXCLUDE list
|
Run through all replication agreements and ensure that EXCLUDE list
|
||||||
has all the required attributes so that we don't cause replication
|
has all the required attributes so that we don't cause replication
|
||||||
storms.
|
storms.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
# We need an IPAdmin connection to the backend
|
# We need an IPAdmin connection to the backend
|
||||||
self.log.debug("Start replication agreement exclude list update task")
|
self.log.debug("Start replication agreement exclude list update task")
|
||||||
|
@ -17,9 +17,8 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# 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 ipalib import api, errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython import ipautil
|
from ipapython import ipautil
|
||||||
from ipapython.dn import DN, EditableDN
|
from ipapython.dn import DN, EditableDN
|
||||||
|
|
||||||
@ -47,7 +46,7 @@ class GenerateUpdateMixin(object):
|
|||||||
We need to separate the deletes that need to happen from the
|
We need to separate the deletes that need to happen from the
|
||||||
new entries that need to be added.
|
new entries that need to be added.
|
||||||
"""
|
"""
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
suffix = ipautil.realm_to_suffix(api.env.realm)
|
suffix = ipautil.realm_to_suffix(api.env.realm)
|
||||||
searchfilter = '(objectclass=*)'
|
searchfilter = '(objectclass=*)'
|
||||||
@ -134,11 +133,10 @@ class GenerateUpdateMixin(object):
|
|||||||
|
|
||||||
return (restart, update_list)
|
return (restart, update_list)
|
||||||
|
|
||||||
class update_managed_post_first(PreUpdate, GenerateUpdateMixin):
|
class update_managed_post_first(Updater, GenerateUpdateMixin):
|
||||||
"""
|
"""
|
||||||
Update managed entries
|
Update managed entries
|
||||||
"""
|
"""
|
||||||
order=FIRST
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
# Never need to restart with the pre-update changes
|
# Never need to restart with the pre-update changes
|
||||||
@ -148,11 +146,10 @@ class update_managed_post_first(PreUpdate, GenerateUpdateMixin):
|
|||||||
|
|
||||||
api.register(update_managed_post_first)
|
api.register(update_managed_post_first)
|
||||||
|
|
||||||
class update_managed_post(PostUpdate, GenerateUpdateMixin):
|
class update_managed_post(Updater, GenerateUpdateMixin):
|
||||||
"""
|
"""
|
||||||
Update managed entries
|
Update managed entries
|
||||||
"""
|
"""
|
||||||
order=LAST
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
(restart, update_list) = self.generate_update(True)
|
(restart, update_list) = self.generate_update(True)
|
||||||
|
@ -17,23 +17,20 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE, LAST
|
|
||||||
from ipaserver.install.plugins.baseupdate import PostUpdate
|
|
||||||
from ipalib import api, errors
|
from ipalib import api, errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import *
|
from ipapython.ipa_log_manager import *
|
||||||
|
|
||||||
|
|
||||||
class update_idrange_type(PostUpdate):
|
class update_idrange_type(Updater):
|
||||||
"""
|
"""
|
||||||
Update all ID ranges that do not have ipaRangeType attribute filled.
|
Update all ID ranges that do not have ipaRangeType attribute filled.
|
||||||
This applies to all ID ranges prior to IPA 3.3.
|
This applies to all ID ranges prior to IPA 3.3.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
base_dn = DN(api.env.container_ranges, api.env.basedn)
|
base_dn = DN(api.env.container_ranges, api.env.basedn)
|
||||||
search_filter = ("(&(objectClass=ipaIDrange)(!(ipaRangeType=*)))")
|
search_filter = ("(&(objectClass=ipaIDrange)(!(ipaRangeType=*)))")
|
||||||
@ -112,16 +109,14 @@ class update_idrange_type(PostUpdate):
|
|||||||
return False, []
|
return False, []
|
||||||
|
|
||||||
|
|
||||||
class update_idrange_baserid(PostUpdate):
|
class update_idrange_baserid(Updater):
|
||||||
"""
|
"""
|
||||||
Update ipa-ad-trust-posix ranges' base RID to 0. This applies to AD trust
|
Update ipa-ad-trust-posix ranges' base RID to 0. This applies to AD trust
|
||||||
posix ranges prior to IPA 4.1.
|
posix ranges prior to IPA 4.1.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
order = LAST
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
base_dn = DN(api.env.container_ranges, api.env.basedn)
|
base_dn = DN(api.env.container_ranges, api.env.basedn)
|
||||||
search_filter = ("(&(objectClass=ipaTrustedADDomainRange)"
|
search_filter = ("(&(objectClass=ipaTrustedADDomainRange)"
|
||||||
|
@ -89,11 +89,9 @@ from ipalib.plugable import Registry
|
|||||||
from ipalib.plugins import aci
|
from ipalib.plugins import aci
|
||||||
from ipalib.plugins.permission import permission, permission_del
|
from ipalib.plugins.permission import permission, permission_del
|
||||||
from ipalib.aci import ACI
|
from ipalib.aci import ACI
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython import ipautil
|
from ipapython import ipautil
|
||||||
from ipaserver.plugins.ldap2 import ldap2
|
from ipaserver.plugins.ldap2 import ldap2
|
||||||
from ipaserver.install.plugins import LAST
|
|
||||||
from ipaserver.install.plugins.baseupdate import PostUpdate
|
|
||||||
|
|
||||||
|
|
||||||
register = Registry()
|
register = Registry()
|
||||||
|
|
||||||
@ -349,14 +347,13 @@ class IncompatibleACIModification(Exception):
|
|||||||
|
|
||||||
|
|
||||||
@register()
|
@register()
|
||||||
class update_managed_permissions(PostUpdate):
|
class update_managed_permissions(Updater):
|
||||||
"""Update managed permissions after an update.
|
"""Update managed permissions after an update.
|
||||||
|
|
||||||
Update managed permissions according to templates specified in plugins.
|
Update managed permissions according to templates specified in plugins.
|
||||||
For read permissions, puts any attributes specified in the legacy
|
For read permissions, puts any attributes specified in the legacy
|
||||||
Anonymous access ACI in the exclude list when creating the permission.
|
Anonymous access ACI in the exclude list when creating the permission.
|
||||||
"""
|
"""
|
||||||
order = LAST
|
|
||||||
|
|
||||||
def get_anonymous_read_aci(self, ldap):
|
def get_anonymous_read_aci(self, ldap):
|
||||||
aciname = u'Enable Anonymous access'
|
aciname = u'Enable Anonymous access'
|
||||||
@ -402,7 +399,7 @@ class update_managed_permissions(PostUpdate):
|
|||||||
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.api.Backend[ldap2]
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
anonymous_read_aci = self.get_anonymous_read_aci(ldap)
|
anonymous_read_aci = self.get_anonymous_read_aci(ldap)
|
||||||
|
|
||||||
|
@ -17,21 +17,18 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE
|
|
||||||
from ipaserver.install.plugins.baseupdate import PostUpdate
|
|
||||||
from ipalib import api, errors
|
from ipalib import api, errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
|
|
||||||
|
|
||||||
class update_pacs(PostUpdate):
|
class update_pacs(Updater):
|
||||||
"""
|
"""
|
||||||
Includes default nfs:None only if no nfs: PAC present in ipakrbauthzdata.
|
Includes default nfs:None only if no nfs: PAC present in ipakrbauthzdata.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dn = DN('cn=ipaConfig', 'cn=etc', api.env.basedn)
|
dn = DN('cn=ipaConfig', 'cn=etc', api.env.basedn)
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
|
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
|
||||||
#
|
#
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE, LAST
|
|
||||||
from ipaserver.install.plugins.baseupdate import PreUpdate, PostUpdate
|
|
||||||
from ipalib import api, errors
|
from ipalib import api, errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import root_logger
|
from ipapython.ipa_log_manager import root_logger
|
||||||
from ipaserver.install import sysupgrade
|
from ipaserver.install import sysupgrade
|
||||||
|
|
||||||
class update_passync_privilege_check(PreUpdate):
|
class update_passync_privilege_check(Updater):
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
update_done = sysupgrade.get_upgrade_state('winsync', 'passsync_privilege_updated')
|
update_done = sysupgrade.get_upgrade_state('winsync', 'passsync_privilege_updated')
|
||||||
@ -24,7 +22,7 @@ class update_passync_privilege_check(PreUpdate):
|
|||||||
self.api.env.container_privilege,
|
self.api.env.container_privilege,
|
||||||
self.api.env.basedn)
|
self.api.env.basedn)
|
||||||
|
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
try:
|
try:
|
||||||
ldap.get_entry(passsync_privilege_dn, [''])
|
ldap.get_entry(passsync_privilege_dn, [''])
|
||||||
except errors.NotFound:
|
except errors.NotFound:
|
||||||
@ -38,13 +36,11 @@ class update_passync_privilege_check(PreUpdate):
|
|||||||
|
|
||||||
api.register(update_passync_privilege_check)
|
api.register(update_passync_privilege_check)
|
||||||
|
|
||||||
class update_passync_privilege_update(PostUpdate):
|
class update_passync_privilege_update(Updater):
|
||||||
"""
|
"""
|
||||||
Add PassSync user as a member of PassSync privilege, if it exists
|
Add PassSync user as a member of PassSync privilege, if it exists
|
||||||
"""
|
"""
|
||||||
|
|
||||||
order = LAST
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
update_done = sysupgrade.get_upgrade_state('winsync', 'passsync_privilege_updated')
|
update_done = sysupgrade.get_upgrade_state('winsync', 'passsync_privilege_updated')
|
||||||
if update_done:
|
if update_done:
|
||||||
@ -52,7 +48,7 @@ class update_passync_privilege_update(PostUpdate):
|
|||||||
return False, []
|
return False, []
|
||||||
|
|
||||||
root_logger.debug("Add PassSync user as a member of PassSync privilege")
|
root_logger.debug("Add PassSync user as a member of PassSync privilege")
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
passsync_dn = DN(('uid','passsync'), ('cn', 'sysaccounts'), ('cn', 'etc'),
|
passsync_dn = DN(('uid','passsync'), ('cn', 'sysaccounts'), ('cn', 'etc'),
|
||||||
api.env.basedn)
|
api.env.basedn)
|
||||||
passsync_privilege_dn = DN(('cn','PassSync Service'),
|
passsync_privilege_dn = DN(('cn','PassSync Service'),
|
||||||
|
@ -2,13 +2,12 @@
|
|||||||
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
|
# Copyright (C) 2014 FreeIPA Contributors see COPYING for license
|
||||||
#
|
#
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE
|
|
||||||
from ipaserver.install.plugins.baseupdate import PreUpdate
|
|
||||||
from ipalib import api, errors
|
from ipalib import api, errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import root_logger
|
from ipapython.ipa_log_manager import root_logger
|
||||||
|
|
||||||
class update_referint(PreUpdate):
|
class update_referint(Updater):
|
||||||
"""
|
"""
|
||||||
Update referential integrity configuration to new style
|
Update referential integrity configuration to new style
|
||||||
http://directory.fedoraproject.org/docs/389ds/design/ri-plugin-configuration.html
|
http://directory.fedoraproject.org/docs/389ds/design/ri-plugin-configuration.html
|
||||||
@ -22,15 +21,13 @@ class update_referint(PreUpdate):
|
|||||||
Old and new style cannot be mixed, all nslapd-pluginArg* attrs have to be removed
|
Old and new style cannot be mixed, all nslapd-pluginArg* attrs have to be removed
|
||||||
"""
|
"""
|
||||||
|
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
referint_dn = DN(('cn', 'referential integrity postoperation'),
|
referint_dn = DN(('cn', 'referential integrity postoperation'),
|
||||||
('cn', 'plugins'), ('cn', 'config'))
|
('cn', 'plugins'), ('cn', 'config'))
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
|
|
||||||
root_logger.debug("Upgrading referential integrity plugin configuration")
|
root_logger.debug("Upgrading referential integrity plugin configuration")
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
try:
|
try:
|
||||||
entry = ldap.get_entry(self.referint_dn)
|
entry = ldap.get_entry(self.referint_dn)
|
||||||
except errors.NotFound:
|
except errors.NotFound:
|
||||||
|
@ -17,23 +17,21 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE
|
|
||||||
from ipaserver.install.plugins.baseupdate import PostUpdate
|
|
||||||
from ipalib import api, errors
|
from ipalib import api, errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import *
|
from ipapython.ipa_log_manager import *
|
||||||
|
|
||||||
|
|
||||||
class update_service_principalalias(PostUpdate):
|
class update_service_principalalias(Updater):
|
||||||
"""
|
"""
|
||||||
Update all services which do not have ipakrbprincipalalias attribute
|
Update all services which do not have ipakrbprincipalalias attribute
|
||||||
used for case-insensitive principal searches filled. This applies for
|
used for case-insensitive principal searches filled. This applies for
|
||||||
all services created prior IPA 3.0.
|
all services created prior IPA 3.0.
|
||||||
"""
|
"""
|
||||||
order = MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
base_dn = DN(api.env.container_service, api.env.basedn)
|
base_dn = DN(api.env.container_service, api.env.basedn)
|
||||||
search_filter = ("(&(objectclass=krbprincipal)(objectclass=ipaservice)"
|
search_filter = ("(&(objectclass=krbprincipal)(objectclass=ipaservice)"
|
||||||
|
@ -17,14 +17,13 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE
|
|
||||||
from ipaserver.install.plugins.baseupdate import PostUpdate, PreUpdate
|
|
||||||
from ipalib import api, errors
|
from ipalib import api, errors
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
from ipapython.ipa_log_manager import *
|
from ipapython.ipa_log_manager import *
|
||||||
|
|
||||||
|
|
||||||
class update_uniqueness_plugins_to_new_syntax(PreUpdate):
|
class update_uniqueness_plugins_to_new_syntax(Updater):
|
||||||
"""
|
"""
|
||||||
Migrate uniqueness plugins to new style syntax
|
Migrate uniqueness plugins to new style syntax
|
||||||
|
|
||||||
@ -165,7 +164,7 @@ class update_uniqueness_plugins_to_new_syntax(PreUpdate):
|
|||||||
return update
|
return update
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
old_style_plugin_search_filter = (
|
old_style_plugin_search_filter = (
|
||||||
"(&"
|
"(&"
|
||||||
|
@ -1,147 +0,0 @@
|
|||||||
# 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.baseupdate import DSRestart
|
|
||||||
from ipaserver.install.ldapupdate import LDAPUpdate
|
|
||||||
from ipapython.ipautil import wait_for_open_socket
|
|
||||||
from ipalib import api
|
|
||||||
from ipalib import backend
|
|
||||||
from ipaplatform.paths import paths
|
|
||||||
from ipapython.dn import DN
|
|
||||||
|
|
||||||
class updateclient(backend.Executioner):
|
|
||||||
"""
|
|
||||||
Backend used for applying LDAP updates via plugins
|
|
||||||
|
|
||||||
An update plugin can be executed before the file-based plugins or
|
|
||||||
afterward. Each plugin returns three values:
|
|
||||||
|
|
||||||
1. restart: dirsrv will be restarted AFTER this update is
|
|
||||||
applied.
|
|
||||||
2. updates: A list of updates to be applied.
|
|
||||||
|
|
||||||
The value of an update is a dictionary with the following possible
|
|
||||||
values:
|
|
||||||
- dn: DN, equal to the dn attribute
|
|
||||||
- updates: list of updates against the dn
|
|
||||||
- default: list of the default entry to be added if it doesn't
|
|
||||||
exist
|
|
||||||
- deleteentry: list of dn's to be deleted (typically single dn)
|
|
||||||
|
|
||||||
For example, this update file:
|
|
||||||
|
|
||||||
dn: cn=global_policy,cn=$REALM,cn=kerberos,$SUFFIX
|
|
||||||
replace:krbPwdLockoutDuration:10::600
|
|
||||||
replace: krbPwdMaxFailure:3::6
|
|
||||||
|
|
||||||
Generates this list which contain the update dictionary:
|
|
||||||
|
|
||||||
[
|
|
||||||
dict(
|
|
||||||
'dn': 'cn=global_policy,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com',
|
|
||||||
'updates': ['replace:krbPwdLockoutDuration:10::600',
|
|
||||||
'replace:krbPwdMaxFailure:3::6']
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
Here is another example showing how a default entry is configured:
|
|
||||||
|
|
||||||
dn: cn=Managed Entries,cn=etc,$SUFFIX
|
|
||||||
default: objectClass: nsContainer
|
|
||||||
default: objectClass: top
|
|
||||||
default: cn: Managed Entries
|
|
||||||
|
|
||||||
This generates:
|
|
||||||
|
|
||||||
[
|
|
||||||
dict(
|
|
||||||
'dn': 'cn=Managed Entries,cn=etc,dc=example,dc=com',
|
|
||||||
'default': ['objectClass:nsContainer',
|
|
||||||
'objectClass:top',
|
|
||||||
'cn:Managed Entries'
|
|
||||||
]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
Note that the variable substitution in both examples has been completed.
|
|
||||||
|
|
||||||
A PRE_UPDATE plugin is executed before file-based updates.
|
|
||||||
|
|
||||||
A POST_UPDATE plugin is executed after file-based updates.
|
|
||||||
|
|
||||||
Plugins are executed automatically when ipa-ldap-updater is run
|
|
||||||
in upgrade mode (--upgrade). They are not executed normally otherwise.
|
|
||||||
To execute plugins as well use the --plugins flag.
|
|
||||||
|
|
||||||
Either may make changes directly in LDAP or can return updates in
|
|
||||||
update format.
|
|
||||||
"""
|
|
||||||
def create_context(self, dm_password):
|
|
||||||
if dm_password:
|
|
||||||
autobind = False
|
|
||||||
else:
|
|
||||||
autobind = True
|
|
||||||
self.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password, autobind=autobind)
|
|
||||||
|
|
||||||
def order(self, updatetype):
|
|
||||||
"""Return plugins of the given updatetype in sorted order.
|
|
||||||
"""
|
|
||||||
ordered = [plugin for plugin in api.Updater()
|
|
||||||
if plugin.updatetype == updatetype]
|
|
||||||
ordered.sort(key=lambda p: p.order)
|
|
||||||
return ordered
|
|
||||||
|
|
||||||
def update(self, updatetype, dm_password, ldapi):
|
|
||||||
"""
|
|
||||||
Execute all update plugins of type updatetype.
|
|
||||||
"""
|
|
||||||
self.create_context(dm_password)
|
|
||||||
kw = dict()
|
|
||||||
result = []
|
|
||||||
ld = LDAPUpdate(dm_password=dm_password, sub_dict={}, ldapi=ldapi)
|
|
||||||
for update in self.order(updatetype):
|
|
||||||
restart, res = self.run(update.name, **kw)
|
|
||||||
|
|
||||||
ld.update_from_dict(res)
|
|
||||||
if restart:
|
|
||||||
# connection has to be closed before restart, otherwise
|
|
||||||
# ld instance will try to reuse old non-valid connection
|
|
||||||
ld.close_connection()
|
|
||||||
self.restart(dm_password)
|
|
||||||
|
|
||||||
self.destroy_context()
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def run(self, method, **kw):
|
|
||||||
"""
|
|
||||||
Execute the update plugin.
|
|
||||||
"""
|
|
||||||
return self.Updater[method](**kw)
|
|
||||||
|
|
||||||
def restart(self, dm_password):
|
|
||||||
dsrestart = DSRestart()
|
|
||||||
socket_name = paths.SLAPD_INSTANCE_SOCKET_TEMPLATE % \
|
|
||||||
api.env.realm.replace('.','-')
|
|
||||||
self.destroy_context()
|
|
||||||
dsrestart.create_instance()
|
|
||||||
wait_for_open_socket(socket_name)
|
|
||||||
self.create_context(dm_password)
|
|
||||||
|
|
||||||
api.register(updateclient)
|
|
@ -17,18 +17,16 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from ipaserver.install.plugins import MIDDLE
|
|
||||||
from ipaserver.install.plugins.baseupdate import PostUpdate
|
|
||||||
from ipaserver.install import certs
|
from ipaserver.install import certs
|
||||||
from ipalib import api, errors, certstore
|
from ipalib import api, errors, certstore
|
||||||
|
from ipalib import Updater
|
||||||
from ipapython import certdb
|
from ipapython import certdb
|
||||||
from ipapython.dn import DN
|
from ipapython.dn import DN
|
||||||
|
|
||||||
class update_upload_cacrt(PostUpdate):
|
class update_upload_cacrt(Updater):
|
||||||
"""
|
"""
|
||||||
Upload public CA certificate to LDAP
|
Upload public CA certificate to LDAP
|
||||||
"""
|
"""
|
||||||
order=MIDDLE
|
|
||||||
|
|
||||||
def execute(self, **options):
|
def execute(self, **options):
|
||||||
db = certs.CertDB(self.api.env.realm)
|
db = certs.CertDB(self.api.env.realm)
|
||||||
@ -45,7 +43,7 @@ class update_upload_cacrt(PostUpdate):
|
|||||||
if ca_chain:
|
if ca_chain:
|
||||||
ca_nickname = ca_chain[-1]
|
ca_nickname = ca_chain[-1]
|
||||||
|
|
||||||
ldap = self.obj.backend
|
ldap = self.api.Backend.ldap2
|
||||||
|
|
||||||
for nickname, trust_flags in db.list_certs():
|
for nickname, trust_flags in db.list_certs():
|
||||||
if 'u' in trust_flags:
|
if 'u' in trust_flags:
|
||||||
|
@ -126,7 +126,7 @@ class IPAUpgrade(service.Service):
|
|||||||
|
|
||||||
def __upgrade(self):
|
def __upgrade(self):
|
||||||
try:
|
try:
|
||||||
ld = ldapupdate.LDAPUpdate(dm_password='', ldapi=True, plugins=True)
|
ld = ldapupdate.LDAPUpdate(dm_password='', ldapi=True)
|
||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user