Add option to specify LDIF file that contains DS configuration changes

This allows to user modify configuration changes of the directory server
instance during installation of DS

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

Also fixes:
https://fedorahosted.org/freeipa/ticket/4048
https://fedorahosted.org/freeipa/ticket/1930

Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
This commit is contained in:
Martin Basti
2015-10-08 10:38:44 +02:00
parent 65c89cc711
commit ae23432ef5
6 changed files with 64 additions and 15 deletions

View File

@@ -74,6 +74,9 @@ Enable debug logging when more verbose output is needed
.TP .TP
\fB\-U\fR, \fB\-\-unattended\fR \fB\-U\fR, \fB\-\-unattended\fR
An unattended installation that will never prompt for user input An unattended installation that will never prompt for user input
.TP
\fB\-\-dirsrv-config-mods\fR
The path to LDIF file that will be used to modify configuration of dse.ldif during installation of the directory server instance
.SS "CERTIFICATE SYSTEM OPTIONS" .SS "CERTIFICATE SYSTEM OPTIONS"
.TP .TP

View File

@@ -78,7 +78,9 @@ Enable debug logging when more verbose output is needed
.TP .TP
\fB\-U\fR, \fB\-\-unattended\fR \fB\-U\fR, \fB\-\-unattended\fR
An unattended installation that will never prompt for user input An unattended installation that will never prompt for user input
.TP
\fB\-\-dirsrv-config-mods\fR
The path to LDIF file that will be used to modify configuration of dse.ldif during installation of the directory server instance
.SS "CERTIFICATE SYSTEM OPTIONS" .SS "CERTIFICATE SYSTEM OPTIONS"
.TP .TP

View File

@@ -206,7 +206,7 @@ info: IPA V2.0
class DsInstance(service.Service): class DsInstance(service.Service):
def __init__(self, realm_name=None, domain_name=None, dm_password=None, def __init__(self, realm_name=None, domain_name=None, dm_password=None,
fstore=None, domainlevel=None): fstore=None, domainlevel=None, config_ldif=None):
service.Service.__init__(self, "dirsrv", service.Service.__init__(self, "dirsrv",
service_desc="directory server", service_desc="directory server",
dm_password=dm_password, dm_password=dm_password,
@@ -229,6 +229,7 @@ class DsInstance(service.Service):
self.subject_base = None self.subject_base = None
self.open_ports = [] self.open_ports = []
self.run_init_memberof = True self.run_init_memberof = True
self.config_ldif = config_ldif # updates for dse.ldif
self.domainlevel = domainlevel self.domainlevel = domainlevel
if realm_name: if realm_name:
self.suffix = ipautil.realm_to_suffix(self.realm) self.suffix = ipautil.realm_to_suffix(self.realm)
@@ -248,6 +249,9 @@ class DsInstance(service.Service):
self.step("creating directory server user", create_ds_user) self.step("creating directory server user", create_ds_user)
self.step("creating directory server instance", self.__create_instance) self.step("creating directory server instance", self.__create_instance)
if self.config_ldif:
self.step("updating configuration in dse.ldif", self.__update_dse_ldif)
self.step("restarting directory server", self.__restart_instance)
self.step("adding default schema", self.__add_default_schemas) self.step("adding default schema", self.__add_default_schemas)
self.step("enabling memberof plugin", self.__add_memberof_module) self.step("enabling memberof plugin", self.__add_memberof_module)
self.step("enabling winsync plugin", self.__add_winsync_module) self.step("enabling winsync plugin", self.__add_winsync_module)
@@ -544,16 +548,39 @@ class DsInstance(service.Service):
# check for open port 389 from now on # check for open port 389 from now on
self.open_ports.append(389) self.open_ports.append(389)
root_logger.debug("restarting ds instance")
try:
self.__restart_instance()
root_logger.debug("done restarting ds instance")
except ipautil.CalledProcessError as e:
print("failed to restart ds instance", e)
root_logger.debug("failed to restart ds instance %s" % e)
inf_fd.close() inf_fd.close()
os.remove(paths.DIRSRV_BOOT_LDIF) os.remove(paths.DIRSRV_BOOT_LDIF)
def __update_dse_ldif(self):
"""
This method updates dse.ldif right after instance creation. This is
supposed to allow admin modify configuration of the DS which has to be
done before IPA is fully installed (for example: settings for
replication on replicas)
DS must be turned off.
"""
self.stop()
dse_filename = os.path.join(
paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % self.serverid,
'dse.ldif'
)
with tempfile.NamedTemporaryFile(delete=False) as new_dse_ldif:
temp_filename = new_dse_ldif.name
with open(dse_filename, "r") as input_file:
parser = installutils.ModifyLDIF(input_file, new_dse_ldif)
# parse modification from config ldif
with open(self.config_ldif, "r") as config_ldif:
parser.modifications_from_ldif(config_ldif)
parser.parse()
new_dse_ldif.flush()
shutil.copy2(temp_filename, dse_filename)
try:
os.remove(temp_filename)
except OSError as e:
root_logger.debug("Failed to clean temporary file: %s" % e)
def __add_default_schemas(self): def __add_default_schemas(self):
pent = pwd.getpwnam(DS_USER) pent = pwd.getpwnam(DS_USER)
for schema_fname in IPA_SCHEMA_FILES: for schema_fname in IPA_SCHEMA_FILES:

View File

@@ -343,6 +343,20 @@ class BaseServer(common.Installable, common.Interactive, core.Composite):
description="Do not automatically create DNS SSHFP records", description="Do not automatically create DNS SSHFP records",
) )
dirsrv_config_mods = Knob(
str, None,
description="The path to LDIF file that will be used to modify "
"configuration of dse.ldif during installation of the "
"directory server instance",
cli_metavar='FILE',
)
@dirsrv_config_mods.validator
def dirsrv_config_mods(self, value):
if not os.path.exists(value):
raise ValueError("File %s does not exist." % value)
def __init__(self, **kwargs): def __init__(self, **kwargs):
super(BaseServer, self).__init__(**kwargs) super(BaseServer, self).__init__(**kwargs)

View File

@@ -734,7 +734,8 @@ def install(installer):
if options.dirsrv_cert_files: if options.dirsrv_cert_files:
ds = dsinstance.DsInstance(fstore=fstore, ds = dsinstance.DsInstance(fstore=fstore,
domainlevel=options.domainlevel) domainlevel=options.domainlevel,
config_ldif=options.dirsrv_config_mods)
installer._ds = ds installer._ds = ds
ds.create_instance(realm_name, host_name, domain_name, ds.create_instance(realm_name, host_name, domain_name,
dm_password, dirsrv_pkcs12_info, dm_password, dirsrv_pkcs12_info,
@@ -743,7 +744,8 @@ def install(installer):
hbac_allow=not options.no_hbac_allow) hbac_allow=not options.no_hbac_allow)
else: else:
ds = dsinstance.DsInstance(fstore=fstore, ds = dsinstance.DsInstance(fstore=fstore,
domainlevel=options.domainlevel) domainlevel=options.domainlevel,
config_ldif=options.dirsrv_config_mods)
installer._ds = ds installer._ds = ds
ds.create_instance(realm_name, host_name, domain_name, ds.create_instance(realm_name, host_name, domain_name,
dm_password, dm_password,

View File

@@ -87,7 +87,7 @@ def install_http_certs(config, fstore):
# FIXME: need Signing-Cert too ? # FIXME: need Signing-Cert too ?
def install_replica_ds(config, promote=False): def install_replica_ds(config, options, promote=False):
dsinstance.check_ports() dsinstance.check_ports()
# if we have a pkcs12 file, create the cert db from # if we have a pkcs12 file, create the cert db from
@@ -95,7 +95,8 @@ def install_replica_ds(config, promote=False):
# cert # cert
pkcs12_info = make_pkcs12_info(config.dir, "dscert.p12", "dirsrv_pin.txt") pkcs12_info = make_pkcs12_info(config.dir, "dscert.p12", "dirsrv_pin.txt")
ds = dsinstance.DsInstance() ds = dsinstance.DsInstance(
config_ldif=options.dirsrv_config_mods)
ds.create_replica( ds.create_replica(
realm_name=config.realm_name, realm_name=config.realm_name,
master_fqdn=config.master_host_name, master_fqdn=config.master_host_name,
@@ -668,7 +669,7 @@ def install(installer):
ntp.create_instance() ntp.create_instance()
# Configure dirsrv # Configure dirsrv
ds = install_replica_ds(config) ds = install_replica_ds(config, options)
# Always try to install DNS records # Always try to install DNS records
install_dns_records(config, options, remote_api) install_dns_records(config, options, remote_api)
@@ -1015,7 +1016,7 @@ def promote(installer):
ntp.create_instance() ntp.create_instance()
# Configure dirsrv # Configure dirsrv
ds = install_replica_ds(config, promote=True) ds = install_replica_ds(config, options, promote=True)
# Always try to install DNS records # Always try to install DNS records
install_dns_records(config, options, api) install_dns_records(config, options, api)