[Freeipa-devel] [PATCH] 0674 Raise an error when a critical DS task fails

2014-11-18 Thread Petr Viktorin
Backup and restore depend on DS tasks succeeding, but they only waited 
for the task to end and didn't check the result.


This patch adds a new helper, run_task, that runs a task, waits for it, 
and checks the result. Backup and restore are changed to use this helper.



--
PetrĀ³
From a557d1e816280719404f7e2dbabad4f425b21e5e Mon Sep 17 00:00:00 2001
From: Petr Viktorin pvikt...@redhat.com
Date: Tue, 18 Nov 2014 14:05:59 +0100
Subject: [PATCH] Raise an error when a critical DS task fails

The backup/restore ignored results of backup/restore task,
because the helper used does not check for errors.

Add an error-checking helper to installutils, and have
backup/restore use it.

The wait_for_task helper is moved to installutils as well. Its
return value is changed. (The return value was always ignored
in current code.)
---
 ipaserver/install/installutils.py | 55 +++
 ipaserver/install/ipa_backup.py   | 19 ++
 ipaserver/install/ipa_restore.py  | 20 +++---
 ipaserver/install/replication.py  | 21 +--
 4 files changed, 61 insertions(+), 54 deletions(-)

diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index d3f09eccb161cc9371fa7c1109816f47194d9cb6..955fa348c6f519b5145288dd58cf8b8ffe997903 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -29,6 +29,7 @@
 import traceback
 import textwrap
 from contextlib import contextmanager
+import time
 
 from dns import resolver, rdatatype
 from dns.exception import DNSException
@@ -46,6 +47,8 @@
 from ipaplatform import services
 from ipaplatform.paths import paths
 
+log = log_mgr.get_logger(__name__)
+
 # Used to determine install status
 IPA_MODULES = [
 'httpd', 'kadmin', 'dirsrv', 'pki-cad', 'pki-tomcatd', 'install',
@@ -1035,3 +1038,55 @@ def load_external_cert(files, subject_base):
 ca_file.flush()
 
 return cert_file, ca_file
+
+
+def wait_for_task(conn, dn):
+Check task status
+
+Task is complete when the nsTaskExitCode attr is set.
+
+:return: the task's entry
+
+Usually you will want to call run_task, which checks the task's exit code
+
+assert isinstance(dn, DN)
+attrlist = [
+'nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode', 'nsTaskCurrentItem',
+'nsTaskTotalItems']
+while True:
+entry = conn.get_entry(dn, attrlist)
+if entry.single_value.get('nsTaskExitCode'):
+break
+time.sleep(1)
+for log_item in entry.get('nsTaskLog', []):
+log.debug('DS task log: %s', log_item)
+return entry
+
+
+def run_task(conn, entry, task_name, raiseonerr=True):
+Run a DS task, wait for it to finish, check it completed successfully
+
+:param conn: connected LDAPClient
+:param entry: task to run, as an LDAP entry
+:param task_name: name to use in messages
+:param raiseonerr: if true (default), raise RuntimeError if the task failed
+
+dn = entry.dn
+try:
+conn.add_entry(entry)
+except Exception as e:
+raise admintool.ScriptError(
+'Unable to add %s task: %s' % (task_name, e))
+
+log.info(Waiting for %s task to finish, task_name)
+entry = wait_for_task(conn, dn)
+exit_code = int(entry.single_value['nsTaskExitCode'])
+if exit_code:
+result = entry.single_value.get('nsTaskStatus', 'no status')
+if raiseonerr:
+raise RuntimeError('%s task failed: %s: %s' % (
+task_name, exit_code, result))
+else:
+log.warn('%s task failed: %s: %s',
+ task_name, exit_code, result)
+log.info(%s task finished, task_name)
diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py
index 682b626e55b9ead5424369e1bab85109ff6b8207..4dc715cf880ee97bc0c27760e5ce3f082b0cef4f 100644
--- a/ipaserver/install/ipa_backup.py
+++ b/ipaserver/install/ipa_backup.py
@@ -35,7 +35,6 @@
 from ipapython.config import IPAOptionParser
 from ipapython.dn import DN
 from ipaserver.install.dsinstance import realm_to_serverid, DS_USER
-from ipaserver.install.replication import wait_for_task
 from ipaserver.install import installutils
 from ipapython import ipaldap
 from ipalib.session import ISO8601_DATETIME_FMT
@@ -403,14 +402,7 @@ def db2ldif(self, instance, backend, online=True):
 }
 )
 
-try:
-conn.add_entry(ent)
-except Exception, e:
-raise admintool.ScriptError('Unable to add LDIF task: %s'
-% e)
-
-self.log.info(Waiting for LDIF to finish)
-wait_for_task(conn, dn)
+installutils.run_task(conn, ent, 'LDIF export')
 else:
 args = ['%s/db2ldif' % self.__find_scripts_dir(instance),
 '-r',
@@ -450,14 +442,7 @@ def db2bak(self, instance, online=True):
 }
 )
 
-try:
-

Re: [Freeipa-devel] [PATCH] 0674 Raise an error when a critical DS task fails

2014-11-18 Thread Petr Vobornik

On 18.11.2014 16:28, Petr Viktorin wrote:

Backup and restore depend on DS tasks succeeding, but they only waited
for the task to end and didn't check the result.

This patch adds a new helper, run_task, that runs a task, waits for it,
and checks the result. Backup and restore are changed to use this helper.



Does not fix, but helps with debugging of issues such as:
* https://fedorahosted.org/freeipa/ticket/4712
* https://fedorahosted.org/freeipa/ticket/4736 (duplicate of 4712)

If ACKed I would also assign it to the ticket 4712.
--
Petr Vobornik

___
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel