freeipa/ipaserver/install/plugins/update_dna_shared_config.py
Stanislav Laznicka 7279ef1d0f Moved update of DNA plugin among update plugins
To make the code more general, moved the update_dna_shared_config
among other update plugins.

Bugfix: DNA shared config connection protocol was compared to a
method string which would result in a try to always update it
even if there was no need to.

https://fedorahosted.org/389/ticket/48373 causes that two
shared DNA config entries are created instead of one.

https://fedorahosted.org/freeipa/ticket/6392

Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
2016-11-11 12:13:56 +01:00

126 lines
4.3 KiB
Python

#
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
#
import time
import ldap
from ipalib.plugable import Registry
from ipalib import errors
from ipalib import Updater
from ipapython.dn import DN
register = Registry()
@register()
class update_dna_shared_config(Updater):
def execute(self, **options):
method = options.get('method', "SASL/GSSAPI")
protocol = options.get('protocol', "LDAP")
dna_bind_method = "dnaRemoteBindMethod"
dna_conn_protocol = "dnaRemoteConnProtocol"
dna_plugin = DN(('cn', 'Distributed Numeric Assignment Plugin'),
('cn', 'plugins'),
('cn', 'config'))
dna_config_base = DN(('cn', 'posix IDs'), dna_plugin)
conn = self.api.Backend.ldap2
# Check the plugin is enabled else it is useless to update
# the shared entry
try:
entry = conn.get_entry(dna_plugin)
if entry.single_value.get('nsslapd-pluginenabled') == 'off':
return False, ()
except errors.NotFound:
self.log.error("Could not find DNA plugin entry: %s" %
dna_config_base)
return False, ()
try:
entry = conn.get_entry(dna_config_base)
except errors.NotFound:
self.log.error("Could not find DNA config entry: %s" %
dna_config_base)
return False, ()
sharedcfgdn = entry.single_value.get("dnaSharedCfgDN")
if sharedcfgdn is not None:
sharedcfgdn = DN(sharedcfgdn)
else:
self.log.error(
"Could not find DNA shared config DN in entry: %s" %
dna_config_base)
return False, ()
#
# Update the shared config entry related to that host
#
# If the shared config entry already exists (like upgrade)
# the update occurs immediately without sleep.
#
# If the shared config entry does not exist (fresh install)
# DS server waits for 30s after its startup to create it.
# Startup likely occurred few sec before this function is
# called so this loop will wait for 30s max.
#
# In case the server is not able to create the entry
# The loop gives a grace period of 60s before logging
# the failure to update the shared config entry and return
#
max_wait = 30
fqdn = self.api.env.host
for _i in range(0, max_wait + 1):
try:
entries = conn.get_entries(
sharedcfgdn, scope=ldap.SCOPE_ONELEVEL,
filter='dnaHostname=%s' % fqdn
)
break
except errors.NotFound:
self.log.debug(
"Unable to find DNA shared config entry for "
"dnaHostname=%s (under %s) so far. Retry in 2 sec." %
(fqdn, sharedcfgdn)
)
time.sleep(2)
else:
self.log.error(
"Could not get dnaHostname entries in {} seconds".format(
max_wait * 2)
)
return False, ()
# If there are several entries, all of them will be updated
# just log a debug msg. This is likely the result of #5510
if len(entries) != 1:
self.log.debug(
"%d entries dnaHostname=%s under %s. One expected" %
(len(entries), fqdn, sharedcfgdn)
)
# time to set the bind method and the protocol in the
# shared config entries
for entry in entries:
update = False
if entry.single_value.get(dna_bind_method) != method:
entry[dna_bind_method] = method
update = True
if entry.single_value.get(dna_conn_protocol) != protocol:
entry[dna_conn_protocol] = protocol
update = True
if update:
try:
conn.update_entry(entry)
except Exception as e:
self.log.error(
"Failed to set SASL/GSSAPI bind method/protocol "
"in entry {}: {}".format(entry, e)
)
# no restart, no update
return False, ()