summaryrefslogtreecommitdiffstats
path: root/ipaserver/install
diff options
context:
space:
mode:
Diffstat (limited to 'ipaserver/install')
-rw-r--r--ipaserver/install/dsinstance.py2
-rw-r--r--ipaserver/install/ldapupdate.py144
-rw-r--r--ipaserver/install/plugins/Makefile.am16
-rw-r--r--ipaserver/install/plugins/__init__.py28
-rw-r--r--ipaserver/install/plugins/baseupdate.py68
-rw-r--r--ipaserver/install/plugins/rename_managed.py132
-rw-r--r--ipaserver/install/plugins/updateclient.py182
-rw-r--r--ipaserver/install/upgradeinstance.py7
8 files changed, 514 insertions, 65 deletions
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 4260579af..77fe7d06d 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -420,7 +420,7 @@ class DsInstance(service.Service):
conn.unbind()
def apply_updates(self):
- ld = ldapupdate.LDAPUpdate(dm_password=self.dm_password, sub_dict=self.sub_dict)
+ ld = ldapupdate.LDAPUpdate(dm_password=self.dm_password, sub_dict=self.sub_dict, plugins=True)
files = ld.get_all_files(ldapupdate.UPDATES_DIR)
ld.update(files)
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 34637c1ee..c396dab6b 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -31,6 +31,7 @@ from ipaserver import ipaldap
from ipapython import entity, ipautil
from ipalib import util
from ipalib import errors
+from ipalib import api
import ldap
from ldap.dn import escape_dn_chars
from ipapython.ipa_log_manager import *
@@ -42,6 +43,8 @@ import os
import pwd
import fnmatch
import csv
+from ipaserver.install.plugins import PRE_UPDATE, POST_UPDATE
+from ipaserver.install.plugins import FIRST, MIDDLE, LAST
class BadSyntax(Exception):
def __init__(self, value):
@@ -49,32 +52,15 @@ class BadSyntax(Exception):
def __str__(self):
return repr(self.value)
-class IPARestart(service.Service):
- """
- Restart the 389 DS service prior to performing deletions.
- """
- def __init__(self, live_run=True):
- """
- This class is present to provide ldapupdate the means to
- restart 389 DS to apply updates prior to performing deletes.
- """
-
- service.Service.__init__(self, "dirsrv")
- self.live_run = live_run
-
- def create_instance(self):
- self.step("stopping directory server", self.stop)
- self.step("starting directory server", self.start)
- self.start_creation("Restarting IPA to initialize updates before performing deletes:")
-
class LDAPUpdate:
def __init__(self, dm_password, sub_dict={}, live_run=True,
- online=True, ldapi=False):
+ online=True, ldapi=False, plugins=False):
"""dm_password = Directory Manager password
sub_dict = substitution dictionary
live_run = Apply the changes or just test
online = do an online LDAP update or use an experimental LDIF updater
ldapi = bind using ldapi. This assumes autobind is enabled.
+ plugins = execute the pre/post update plugins
"""
self.sub_dict = sub_dict
self.live_run = live_run
@@ -83,6 +69,7 @@ class LDAPUpdate:
self.modified = False
self.online = online
self.ldapi = ldapi
+ self.plugins = plugins
self.pw_name = pwd.getpwuid(os.geteuid()).pw_name
if sub_dict.get("REALM"):
@@ -554,11 +541,11 @@ class LDAPUpdate:
# skip this update type, it occurs in __delete_entries()
return None
elif utype == 'replace':
- # v has the format "old:: new"
+ # v has the format "old::new"
try:
(old, new) = v.split('::', 1)
except ValueError:
- raise BadSyntax, "bad syntax in replace, needs to be in the format old: new in %s" % v
+ raise BadSyntax, "bad syntax in replace, needs to be in the format old::new in %s" % v
try:
e.remove(old)
e.append(new)
@@ -708,11 +695,12 @@ class LDAPUpdate:
deletes = updates.get('deleteentry', [])
for d in deletes:
try:
- if self.live_run:
- self.conn.deleteEntry(dn)
- self.modified = True
+ root_logger.info('Deleting entry %s", dn)
+ if self.live_run:
+ self.conn.deleteEntry(dn)
+ self.modified = True
except errors.NotFound, e:
- root_logger.info("Deleting non-existent entry %s", e)
+ root_logger.info("%s did not exist:%s", (dn, e))
self.modified = True
except errors.DatabaseError, e:
root_logger.error("Delete failed: %s", e)
@@ -724,11 +712,12 @@ class LDAPUpdate:
if utype == 'deleteentry':
try:
- if self.live_run:
- self.conn.deleteEntry(dn)
- self.modified = True
+ root_logger.info('Deleting entry %s", dn)
+ if self.live_run:
+ self.conn.deleteEntry(dn)
+ self.modified = True
except errors.NotFound, e:
- root_logger.info("Deleting non-existent entry %s", e)
+ root_logger.info("%s did not exist:%s", (dn, e))
self.modified = True
except errors.DatabaseError, e:
root_logger.error("Delete failed: %s", e)
@@ -772,16 +761,49 @@ class LDAPUpdate:
else:
raise RuntimeError("Offline updates are not supported.")
+ def __run_updates(self, dn_list, all_updates):
+ # For adds and updates we want to apply updates from shortest
+ # to greatest length of the DN. For deletes we want the reverse.
+ sortedkeys = dn_list.keys()
+ sortedkeys.sort()
+ for k in sortedkeys:
+ for dn in dn_list[k]:
+ self.__update_record(all_updates[dn])
+
+ sortedkeys.reverse()
+ for k in sortedkeys:
+ for dn in dn_list[k]:
+ self.__delete_record(all_updates[dn])
+
def update(self, files):
"""Execute the update. files is a list of the update files to use.
returns True if anything was changed, otherwise False
"""
+ updates = None
+ if self.plugins:
+ logging.info('PRE_UPDATE')
+ updates = api.Backend.updateclient.update(PRE_UPDATE, self.dm_password, self.ldapi, self.live_run)
+
try:
self.create_connection()
all_updates = {}
dn_list = {}
+ # Start with any updates passed in from pre-update plugins
+ if updates:
+ for entry in updates:
+ all_updates.update(entry)
+ for upd in updates:
+ for dn in upd:
+ dn_explode = ldap.explode_dn(dn.lower())
+ l = len(dn_explode)
+ if dn_list.get(l):
+ if dn not in dn_list[l]:
+ dn_list[l].append(dn)
+ else:
+ dn_list[l] = [dn]
+
for f in files:
try:
root_logger.info("Parsing file %s" % f)
@@ -792,40 +814,38 @@ class LDAPUpdate:
(all_updates, dn_list) = self.parse_update_file(data, all_updates, dn_list)
- # Process Managed Entry Updates
- managed_entries = self.__update_managed_entries()
- if managed_entries:
- managed_entry_dns = [[m[entry]['dn'] for entry in m] for m in managed_entries]
- l = len(dn_list.keys())
-
- # Add Managed Entry DN's to the DN List
- for dn in managed_entry_dns:
- l+=1
- dn_list[l] = dn
- # Add Managed Entry Updates to All Updates List
- for managed_entry in managed_entries:
- all_updates.update(managed_entry)
-
- # For adds and updates we want to apply updates from shortest
- # to greatest length of the DN. For deletes we want the reverse.
- sortedkeys = dn_list.keys()
- sortedkeys.sort()
- for k in sortedkeys:
- for dn in dn_list[k]:
- self.__update_record(all_updates[dn])
-
- # Restart 389 Directory Service
- socket_name = '/var/run/slapd-%s.socket' % self.realm.replace('.','-')
- iparestart = IPARestart()
- iparestart.create_instance()
- installutils.wait_for_open_socket(socket_name)
- self.create_connection()
-
- sortedkeys.reverse()
- for k in sortedkeys:
- for dn in dn_list[k]:
- self.__delete_record(all_updates[dn])
+ self.__run_updates(dn_list, all_updates)
finally:
if self.conn: self.conn.unbind()
+ if self.plugins:
+ logging.info('POST_UPDATE')
+ updates = api.Backend.updateclient.update(POST_UPDATE, self.dm_password, self.ldapi, self.live_run)
+ dn_list = {}
+ for upd in updates:
+ for dn in upd:
+ dn_explode = ldap.explode_dn(dn.lower())
+ l = len(dn_explode)
+ if dn_list.get(l):
+ if dn not in dn_list[l]:
+ dn_list[l].append(dn)
+ else:
+ dn_list[l] = [dn]
+ self.__run_updates(dn_list, updates)
+
+ return self.modified
+
+
+ def update_from_dict(self, dn_list, updates):
+ """
+ Apply updates internally as opposed to from a file.
+
+ dn_list is a list of dns to be updated
+ updates is a dictionary containing the updates
+ """
+ if not self.conn:
+ self.create_connection()
+
+ self.__run_updates(dn_list, updates)
+
return self.modified
diff --git a/ipaserver/install/plugins/Makefile.am b/ipaserver/install/plugins/Makefile.am
new file mode 100644
index 000000000..a96d0be5c
--- /dev/null
+++ b/ipaserver/install/plugins/Makefile.am
@@ -0,0 +1,16 @@
+NULL =
+
+appdir = $(pythondir)/ipaserver/install
+app_PYTHON = \
+ __init__.py \
+ baseupdate.py \
+ rename_managed.py \
+ updateclient.py \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
diff --git a/ipaserver/install/plugins/__init__.py b/ipaserver/install/plugins/__init__.py
new file mode 100644
index 000000000..49bef4df8
--- /dev/null
+++ b/ipaserver/install/plugins/__init__.py
@@ -0,0 +1,28 @@
+# 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/>.
+
+"""
+Provide a separate api for updates.
+"""
+PRE_UPDATE = 1
+POST_UPDATE = 2
+
+FIRST = 1
+MIDDLE = 2
+LAST = 4
diff --git a/ipaserver/install/plugins/baseupdate.py b/ipaserver/install/plugins/baseupdate.py
new file mode 100644
index 000000000..227dc917a
--- /dev/null
+++ b/ipaserver/install/plugins/baseupdate.py
@@ -0,0 +1,68 @@
+# 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 ipalib import api
+from ipalib import errors
+from ipalib import Updater, Object
+from ipaserver.install import service
+from ipaserver.install.plugins import PRE_UPDATE, POST_UPDATE, MIDDLE
+
+class DSRestart(service.Service):
+ """
+ Restart the 389-ds service.
+ """
+ def __init__(self):
+ """
+ This class is present to provide ldapupdate the means to
+ restart 389-ds.
+ """
+ service.Service.__init__(self, "dirsrv")
+
+ def create_instance(self):
+ self.step("stopping directory server", self.stop)
+ self.step("starting directory server", self.start)
+ self.start_creation("Restarting Directory server to apply updates")
+
+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__()
diff --git a/ipaserver/install/plugins/rename_managed.py b/ipaserver/install/plugins/rename_managed.py
new file mode 100644
index 000000000..a9eed0be3
--- /dev/null
+++ b/ipaserver/install/plugins/rename_managed.py
@@ -0,0 +1,132 @@
+# 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 import PRE_UPDATE, POST_UPDATE, FIRST, LAST
+from ipaserver.install.plugins import PRE_UPDATE, POST_UPDATE, FIRST, LAST
+from ipaserver.install.plugins.baseupdate import PreUpdate, PostUpdate
+from ipalib.frontend import Updater
+from ipaserver.install.plugins import baseupdate
+from ipalib import api, errors
+from ipapython import ipautil
+import ldap as _ldap
+
+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 i in xrange(len(entry[attr])):
+ update.append('%s:%s' % (str(attr), str(entry[attr][i])))
+ else:
+ update.append('%s:%s' % (str(attr), str(entry[attr])))
+
+ return update
+
+def generate_update(ldap, deletes=False):
+ """
+ We need to separate the deletes that need to happen from the
+ new entries that need to be added.
+ """
+ suffix = ipautil.realm_to_suffix(api.env.realm)
+ searchfilter = '(objectclass=*)'
+ definitions_managed_entries = []
+ old_template_container = 'cn=etc,%s' % suffix
+ old_definition_container = 'cn=managed entries,cn=plugins,cn=config'
+ new = 'cn=Managed Entries,cn=etc,%s' % suffix
+ sub = ['cn=Definitions,', 'cn=Templates,']
+ new_managed_entries = []
+ old_templates = []
+ template = None
+ 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, normalize=False
+ )
+ except errors.NotFound, e:
+ return (False, new_managed_entries)
+
+ for entry in definitions_managed_entries:
+ new_definition = {}
+ definition_managed_entry_updates = {}
+ if deletes:
+ old_definition = {'dn': str(entry[0]), 'deleteentry': ['dn: %s' % str(entry[0])]}
+ old_template = str(entry[1]['managedtemplate'][0])
+ definition_managed_entry_updates[old_definition['dn']] = old_definition
+ old_templates.append(old_template)
+ else:
+ entry[1]['managedtemplate'] = str(entry[1]['managedtemplate'][0].replace(old_template_container, sub[1] + new))
+ new_definition['dn'] = str(entry[0].replace(old_definition_container, sub[0] + new))
+ new_definition['default'] = entry_to_update(entry[1])
+ definition_managed_entry_updates[new_definition['dn']] = new_definition
+ new_managed_entries.append(definition_managed_entry_updates)
+ for old_template in old_templates: # Only happens when deletes is True
+ try:
+ (dn, template) = ldap.get_entry(old_template, ['*'], normalize=False)
+ dn = str(dn)
+ new_template = {}
+ template_managed_entry_updates = {}
+ old_template = {'dn': dn, 'deleteentry': ['dn: %s' % dn]}
+ new_template['dn'] = str(dn.replace(old_template_container, sub[1] + new))
+ new_template['default'] = entry_to_update(template)
+ template_managed_entry_updates[new_template['dn']] = new_template
+ template_managed_entry_updates[old_template['dn']] = old_template
+ new_managed_entries.append(template_managed_entry_updates)
+ except errors.NotFound, e:
+ pass
+
+ if len(new_managed_entries) > 0:
+ restart = True
+ new_managed_entries.sort(reverse=True)
+
+ return (restart, new_managed_entries)
+
+class update_managed_post_first(PreUpdate):
+ """
+ Update managed entries
+ """
+ order=FIRST
+
+ def execute(self, **options):
+ # Never need to restart with the pre-update changes
+ (ignore, new_managed_entries) = generate_update(self.obj.backend, False)
+
+ return (False, True, new_managed_entries)
+
+api.register(update_managed_post_first)
+
+class update_managed_post(PostUpdate):
+ """
+ Update managed entries
+ """
+ order=LAST
+
+ def execute(self, **options):
+ (restart, new_managed_entries) = generate_update(self.obj.backend, True)
+
+ return (restart, True, new_managed_entries)
+
+api.register(update_managed_post)
diff --git a/ipaserver/install/plugins/updateclient.py b/ipaserver/install/plugins/updateclient.py
new file mode 100644
index 000000000..8f463fa69
--- /dev/null
+++ b/ipaserver/install/plugins/updateclient.py
@@ -0,0 +1,182 @@
+# 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 os
+from ipaserver.install import installutils
+from ipaserver.install.plugins import FIRST, MIDDLE, LAST
+from ipaserver.install.plugins import POST_UPDATE
+from ipaserver.install.plugins.baseupdate import DSRestart
+from ipaserver.install.ldapupdate import LDAPUpdate
+from ipalib import api
+from ipalib import backend
+import ldap as _ldap
+
+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 needs to be restarted BEFORE this update is
+ applied.
+ 2. apply_now: when True the update is applied when the plugin
+ returns. Otherwise the update is cached until all
+ plugins of that update type are complete, then they
+ are applied together.
+ 3. updates: A dictionary of updates to be applied.
+
+ updates is a dictionary keyed on dn. The value of an update is a
+ dictionary with the following possible values:
+ - dn: str, duplicate of the key
+ - 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 update dictionary:
+
+ dict('cn=global_policy,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com':
+ 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('cn=Managed Entries,cn=etc,dc=example,dc=com',
+ 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='cn=Directory Manager', bind_pw=dm_password, autobind=autobind)
+
+ def order(self, updatetype):
+ """
+ Calculate rough order of plugins.
+ """
+ order = []
+ for plugin in api.Updater(): #pylint: disable=E1101
+ if plugin.updatetype != updatetype:
+ continue
+ if plugin.order == FIRST:
+ order.insert(0, plugin)
+ elif plugin.order == MIDDLE:
+ order.insert(len(order)/2, plugin)
+ else:
+ order.append(plugin)
+
+ for o in order:
+ yield o
+
+ def update(self, updatetype, dm_password, ldapi, live_run):
+ """
+ Execute all update plugins of type updatetype.
+ """
+ self.create_context(dm_password)
+ kw = dict(live_run=live_run)
+ result = []
+ ld = LDAPUpdate(dm_password=dm_password, sub_dict={}, live_run=live_run, ldapi=ldapi)
+ for update in self.order(updatetype):
+ (restart, apply_now, res) = self.run(update.name, **kw)
+ if restart:
+ self.restart(dm_password, live_run)
+ dn_list = {}
+ for upd in res:
+ for dn in upd:
+ dn_explode = _ldap.explode_dn(dn.lower())
+ l = len(dn_explode)
+ if dn_list.get(l):
+ if dn not in dn_list[l]:
+ dn_list[l].append(dn)
+ else:
+ dn_list[l] = [dn]
+ updates = {}
+ for entry in res:
+ updates.update(entry)
+
+ if apply_now:
+ ld.update_from_dict(dn_list, updates)
+ elif res:
+ result.extend(res)
+
+ self.destroy_context()
+
+ return result
+
+ def run(self, method, **kw):
+ """
+ Execute the update plugin.
+ """
+ return self.Updater[method](**kw) #pylint: disable=E1101
+
+ def restart(self, dm_password, live_run):
+ if os.getegid() != 0:
+ self.log.warn("Not root, skipping restart")
+ return
+ dsrestart = DSRestart()
+ socket_name = '/var/run/slapd-%s.socket' % \
+ api.env.realm.replace('.','-')
+ if live_run:
+ self.destroy_context()
+ dsrestart.create_instance()
+ installutils.wait_for_open_socket(socket_name)
+ self.create_context(dm_password)
+ else:
+ self.log.warn("Test mode, skipping restart")
+
+api.register(updateclient)
diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py
index 72636497c..0913fdb45 100644
--- a/ipaserver/install/upgradeinstance.py
+++ b/ipaserver/install/upgradeinstance.py
@@ -21,6 +21,7 @@ import os
import sys
import shutil
import random
+import traceback
from ipapython.ipa_log_manager import *
from ipaserver.install import installutils
@@ -100,11 +101,12 @@ class IPAUpgrade(service.Service):
def __upgrade(self):
try:
- ld = ldapupdate.LDAPUpdate(dm_password='', ldapi=True, live_run=self.live_run)
+ ld = ldapupdate.LDAPUpdate(dm_password='', ldapi=True, live_run=self.live_run, plugins=True)
if len(self.files) == 0:
self.files = ld.get_all_files(ldapupdate.UPDATES_DIR)
self.modified = ld.update(self.files)
- except ldapupdate.BadSyntax:
+ except ldapupdate.BadSyntax, e:
+ logging.error('Bad syntax in upgrade %s' % str(e))
self.modified = False
self.badsyntax = True
except Exception, e:
@@ -112,6 +114,7 @@ class IPAUpgrade(service.Service):
self.modified = False
self.upgradefailed = True
root_logger.error('Upgrade failed with %s' % str(e))
+ root_logger.debug('%s', traceback.format_exc())
def main():
if os.getegid() != 0: