mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Server Upgrade: use LDIF parser to modify DSE.ldif
Ticket: https://fedorahosted.org/freeipa/ticket/4925 Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
This commit is contained in:
parent
522cbb23f1
commit
882ce85ad5
@ -17,6 +17,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import ldif
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
@ -32,6 +33,116 @@ from ipaserver.install import service
|
||||
|
||||
DSE = 'dse.ldif'
|
||||
|
||||
|
||||
class GetEntryFromLDIF(ldif.LDIFParser):
|
||||
"""
|
||||
LDIF parser.
|
||||
To get results, method parse() must be called first, then method
|
||||
get_results() which return parsed entries
|
||||
"""
|
||||
def __init__(self, input_file, entries_dn=[]):
|
||||
"""
|
||||
Parse LDIF file.
|
||||
:param input_file: an LDIF file to be parsed
|
||||
:param entries_dn: list of DN which will be returned. All entries are
|
||||
returned if list is empty.
|
||||
"""
|
||||
ldif.LDIFParser.__init__(self, input_file)
|
||||
self.entries_dn = entries_dn
|
||||
self.results = {}
|
||||
|
||||
def get_results(self):
|
||||
"""
|
||||
Returns results in dictionary {DN: entry, ...}
|
||||
"""
|
||||
return self.results
|
||||
|
||||
def handle(self, dn, entry):
|
||||
if self.entries_dn and dn not in self.entries_dn:
|
||||
return
|
||||
|
||||
self.results[dn] = entry
|
||||
|
||||
|
||||
class ModifyLDIF(ldif.LDIFParser):
|
||||
"""
|
||||
Allows to modify LDIF file.
|
||||
|
||||
Remove operations are executed before add operations
|
||||
"""
|
||||
def __init__(self, input_file, writer):
|
||||
"""
|
||||
:param input_file: an LDIF
|
||||
:param writer: ldif.LDIFWriter instance where modified LDIF will
|
||||
be written
|
||||
"""
|
||||
ldif.LDIFParser.__init__(self, input_file)
|
||||
self.writer = writer
|
||||
|
||||
self.add_dict = {}
|
||||
self.remove_dict = {}
|
||||
|
||||
def add_value(self, dn, attr, value):
|
||||
"""
|
||||
Add value to LDIF.
|
||||
:param dn: DN of entry (must exists)
|
||||
:param attr: attribute name
|
||||
:param value: value to be added
|
||||
"""
|
||||
attr = attr.lower()
|
||||
entry = self.add_dict.setdefault(dn, {})
|
||||
attribute = entry.setdefault(attr, [])
|
||||
if value not in attribute:
|
||||
attribute.append(value)
|
||||
|
||||
def remove_value(self, dn, attr, value=None):
|
||||
"""
|
||||
Remove value from LDIF.
|
||||
:param dn: DN of entry
|
||||
:param attr: attribute name
|
||||
:param value: value to be removed, if value is None, attribute will
|
||||
be removed
|
||||
"""
|
||||
attr = attr.lower()
|
||||
entry = self.remove_dict.setdefault(dn, {})
|
||||
|
||||
if entry is None:
|
||||
return
|
||||
attribute = entry.setdefault(attr, [])
|
||||
if value is None:
|
||||
# remove all values
|
||||
entry[attr] = None
|
||||
return
|
||||
elif attribute is None:
|
||||
# already marked to remove all values
|
||||
return
|
||||
if value not in attribute:
|
||||
attribute.append(value)
|
||||
|
||||
def handle(self, dn, entry):
|
||||
if dn in self.remove_dict:
|
||||
for name, value in self.remove_dict[dn].iteritems():
|
||||
if value is None:
|
||||
attribute = []
|
||||
else:
|
||||
attribute = entry.setdefault(name, [])
|
||||
attribute = [v for v in attribute if v not in value]
|
||||
entry[name] = attribute
|
||||
|
||||
if not attribute: # empty
|
||||
del entry[name]
|
||||
|
||||
if dn in self.add_dict:
|
||||
for name, value in self.add_dict[dn].iteritems():
|
||||
attribute = entry.setdefault(name, [])
|
||||
attribute.extend([v for v in value if v not in attribute])
|
||||
|
||||
if not entry: # empty
|
||||
return
|
||||
|
||||
self.writer.unparse(dn, entry)
|
||||
|
||||
|
||||
class IPAUpgrade(service.Service):
|
||||
"""
|
||||
Update the LDAP data in an instance by turning off all network
|
||||
@ -89,34 +200,68 @@ class IPAUpgrade(service.Service):
|
||||
|
||||
def __save_config(self):
|
||||
shutil.copy2(self.filename, self.savefilename)
|
||||
port = installutils.get_directive(self.filename, 'nsslapd-port',
|
||||
separator=':')
|
||||
security = installutils.get_directive(self.filename, 'nsslapd-security',
|
||||
separator=':')
|
||||
with open(self.filename, "rb") as in_file:
|
||||
parser = GetEntryFromLDIF(in_file, entries_dn=["cn=config"])
|
||||
parser.parse()
|
||||
try:
|
||||
config_entry = parser.get_results()["cn=config"]
|
||||
except KeyError:
|
||||
raise RuntimeError("Unable to find cn=config entry in %s" %
|
||||
self.filename)
|
||||
|
||||
self.backup_state('nsslapd-port', port)
|
||||
self.backup_state('nsslapd-security', security)
|
||||
try:
|
||||
port = config_entry['nsslapd-port'][0]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
self.backup_state('nsslapd-port', port)
|
||||
|
||||
try:
|
||||
security = config_entry['nsslapd-security'][0]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
self.backup_state('nsslapd-security', security)
|
||||
|
||||
def __restore_config(self):
|
||||
port = self.restore_state('nsslapd-port')
|
||||
security = self.restore_state('nsslapd-security')
|
||||
|
||||
if port is not None:
|
||||
installutils.set_directive(
|
||||
self.filename, 'nsslapd-port', port,
|
||||
quotes=False, separator=':')
|
||||
if security is not None:
|
||||
installutils.set_directive(
|
||||
self.filename, 'nsslapd-security', security,
|
||||
quotes=False, separator=':')
|
||||
ldif_outfile = "%s.modified.out" % self.filename
|
||||
with open(ldif_outfile, "wb") as out_file:
|
||||
ldif_writer = ldif.LDIFWriter(out_file)
|
||||
with open(self.filename, "rb") as in_file:
|
||||
parser = ModifyLDIF(in_file, ldif_writer)
|
||||
|
||||
if port is not None:
|
||||
parser.remove_value("cn=config", "nsslapd-port")
|
||||
parser.add_value("cn=config", "nsslapd-port", port)
|
||||
if security is not None:
|
||||
parser.remove_value("cn=config", "nsslapd-security")
|
||||
parser.add_value("cn=config", "nsslapd-security", security)
|
||||
|
||||
parser.parse()
|
||||
|
||||
shutil.copy2(ldif_outfile, self.filename)
|
||||
|
||||
def __disable_listeners(self):
|
||||
installutils.set_directive(self.filename, 'nsslapd-port',
|
||||
0, quotes=False, separator=':')
|
||||
installutils.set_directive(self.filename, 'nsslapd-security',
|
||||
'off', quotes=False, separator=':')
|
||||
installutils.set_directive(self.filename, 'nsslapd-ldapientrysearchbase',
|
||||
None, quotes=False, separator=':')
|
||||
ldif_outfile = "%s.modified.out" % self.filename
|
||||
with open(ldif_outfile, "wb") as out_file:
|
||||
ldif_writer = ldif.LDIFWriter(out_file)
|
||||
with open(self.filename, "rb") as in_file:
|
||||
parser = ModifyLDIF(in_file, ldif_writer)
|
||||
|
||||
parser.remove_value("cn=config", "nsslapd-port")
|
||||
parser.add_value("cn=config", "nsslapd-port", "0")
|
||||
|
||||
parser.remove_value("cn=config", "nsslapd-security")
|
||||
parser.add_value("cn=config", "nsslapd-security", "off")
|
||||
|
||||
parser.remove_value("cn=config", "nsslapd-ldapientrysearchbase")
|
||||
|
||||
parser.parse()
|
||||
|
||||
shutil.copy2(ldif_outfile, self.filename)
|
||||
|
||||
def __update_schema(self):
|
||||
self.modified = schemaupdate.update_schema(
|
||||
|
Loading…
Reference in New Issue
Block a user