This fixes https://fedorahosted.org/freeipa/ticket/2071 (Add final debug message in installers).

I submitted an earlier version of this patch before (0014), but it was too much to include in 2.2. Hopefully now there's more space for restructuring. I think it's better to start a new thread with this approach.

The try/except blocks at the end of installers/management scripts are replaced by a call to a common function, which includes the final message. For each specific error, the error handlers in all scripts was almost the same, but each script handled a different selection of errors. Instead of having this copy/pasted code (with subtle differences creeping in over time), this patch consolidates it all in one place.




--
PetrĀ³

From 2abfc82aff1b685291f5a7670eeb18b29bdce177 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Fri, 20 Apr 2012 04:39:59 -0400
Subject: [PATCH] Move install script error handling to a common function

All of our install/admin scripts had a try/except block calling the
main function and handling common exceptions. These were copy-pasted
from each other and modified to various levels of sophistication.
This refactors them out to a single function, which includes a final
pass/fail message for all of the scripts.

https://fedorahosted.org/freeipa/ticket/2071
---
 install/tools/ipa-adtrust-install    |   34 ++-------
 install/tools/ipa-ca-install         |   65 +++++++-----------
 install/tools/ipa-compat-manage      |   23 +------
 install/tools/ipa-compliance         |   14 ++---
 install/tools/ipa-csreplica-manage   |   18 +----
 install/tools/ipa-dns-install        |   34 ++-------
 install/tools/ipa-ldap-updater       |   20 ++----
 install/tools/ipa-managed-entries    |   19 +-----
 install/tools/ipa-nis-manage         |   23 +------
 install/tools/ipa-replica-conncheck  |   11 +---
 install/tools/ipa-replica-install    |   64 +++++++-----------
 install/tools/ipa-replica-manage     |   25 +------
 install/tools/ipa-replica-prepare    |   23 ++-----
 install/tools/ipa-server-certinstall |   14 ++---
 install/tools/ipa-server-install     |   57 +++++++---------
 install/tools/ipa-upgradeconfig      |    9 +--
 install/tools/ipactl                 |   30 ++------
 ipaserver/install/installutils.py    |  127 ++++++++++++++++++++++++++++++++++
 ipaserver/install/ldapupdate.py      |    5 +-
 19 files changed, 260 insertions(+), 355 deletions(-)

diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install
index 248ea35eaa86dd59ebbc871b86df780cfd71ccf6..0dfc6eba6568f2388fb2bec8319acf593ad838a9 100755
--- a/install/tools/ipa-adtrust-install
+++ b/install/tools/ipa-adtrust-install
@@ -21,8 +21,6 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-import traceback
-
 from ipaserver.plugins.ldap2 import ldap2
 from ipaserver.install import adtrustinstance
 from ipaserver.install.installutils import *
@@ -35,6 +33,8 @@ import krbV
 import ldap
 from ipapython.ipa_log_manager import *
 
+log_file_name = "/var/log/ipaserver-install.log"
+
 def parse_options():
     parser = IPAOptionParser(version=version.VERSION)
     parser.add_option("-p", "--ds-password", dest="dm_password",
@@ -86,8 +86,8 @@ def main():
     if os.getegid() != 0:
         sys.exit("Must be root to setup AD trusts on server")
 
-    standard_logging_setup("/var/log/ipaserver-install.log", debug=options.debug, filemode='a')
-    print "\nThe log file for this installation can be found in /var/log/ipaserver-install.log"
+    standard_logging_setup(log_file_name, debug=options.debug, filemode='a')
+    print "\nThe log file for this installation can be found in %s" % log_file_name
 
     root_logger.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
     root_logger.debug("missing options might be asked for interactively later\n")
@@ -227,26 +227,6 @@ def main():
 
     return 0
 
-try:
-    sys.exit(main())
-except SystemExit, e:
-    sys.exit(e)
-except KeyboardInterrupt:
-    print "Installation cancelled."
-except RuntimeError, e:
-    print str(e)
-except HostnameLocalhost:
-    print "The hostname resolves to the localhost address (127.0.0.1/::1)"
-    print "Please change your /etc/hosts file so that the hostname"
-    print "resolves to the ip address of your network interface."
-    print "The KDC service does not listen on localhost"
-    print ""
-    print "Please fix your /etc/hosts file and restart the setup program"
-except Exception, e:
-    message = "Unexpected error - see ipaserver-install.log for details:\n %s" % str(e)
-    print message
-    message = str(e)
-    for str in traceback.format_tb(sys.exc_info()[2]):
-        message = message + "\n" + str
-    root_logger.debug(message)
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, log_file_name=log_file_name,
+            operation_name='ipa-adtrust-install')
diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index 57f867e704b559a691ac48a564c152e3b98def72..22b5982cb34a78db4e9950ac9e23d7bbd58ddb32 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -21,7 +21,7 @@
 import sys
 import socket
 
-import os, traceback, shutil
+import os, shutil
 
 from ipapython import ipautil
 from ipapython import services as ipaservices
@@ -39,8 +39,9 @@ from ipapython.config import IPAOptionParser
 from ipapython import sysrestore
 from ipapython.ipa_log_manager import *
 
-CACERT="/etc/ipa/ca.crt"
-REPLICA_INFO_TOP_DIR=None
+log_file_name = "/var/log/ipareplica-ca-install.log"
+CACERT = "/etc/ipa/ca.crt"
+REPLICA_INFO_TOP_DIR = None
 
 def parse_options():
     usage = "%prog [options] REPLICA_FILE"
@@ -72,7 +73,12 @@ def get_dirman_password():
 
 def main():
     safe_options, options, filename = parse_options()
-    standard_logging_setup("/var/log/ipareplica-ca-install.log", debug=options.debug)
+
+    if os.geteuid() != 0:
+        sys.exit("\nYou must be root to run this script.\n")
+
+    standard_logging_setup(log_file_name, debug=options.debug)
+
     root_logger.debug('%s was invoked with argument "%s" and options: %s' % (sys.argv[0], filename, safe_options))
 
     if not ipautil.file_exists(filename):
@@ -150,41 +156,20 @@ def main():
     # We need to restart apache as we drop a new config file in there
     ipaservices.knownservices.httpd.restart(capture_output=True)
 
-try:
-    if not os.geteuid()==0:
-        sys.exit("\nYou must be root to run this script.\n")
+fail_message = '''
+Your system may be partly configured.
+Run /usr/sbin/ipa-server-install --uninstall to clean up.
+'''
 
-    main()
-    sys.exit(0)
-except SystemExit, e:
-    sys.exit(e)
-except socket.error, (errno, errstr):
-    print errstr
-except HostnameLocalhost:
-    print "The hostname resolves to the localhost address (127.0.0.1/::1)"
-    print "Please change your /etc/hosts file so that the hostname"
-    print "resolves to the ip address of your network interface."
-    print ""
-    print "Please fix your /etc/hosts file and restart the setup program"
-except Exception, e:
-    print "creation of replica failed: %s" % str(e)
-    message = str(e)
-    for str in traceback.format_tb(sys.exc_info()[2]):
-        message = message + "\n" + str
-    root_logger.debug(message)
-except KeyboardInterrupt:
-    print "Installation cancelled."
-finally:
-    # always try to remove decrypted replica file
+if __name__ == '__main__':
     try:
-        if REPLICA_INFO_TOP_DIR:
-            shutil.rmtree(REPLICA_INFO_TOP_DIR)
-    except OSError:
-        pass
-
-print ""
-print "Your system may be partly configured."
-print "Run /usr/sbin/ipa-server-install --uninstall to clean up."
-
-# the only way to get here is on error or ^C
-sys.exit(1)
+        installutils.run_script(main, log_file_name=log_file_name,
+                operation_name='ipa-ca-install',
+                fail_message=fail_message)
+    finally:
+        # always try to remove decrypted replica file
+        try:
+            if REPLICA_INFO_TOP_DIR:
+                shutil.rmtree(REPLICA_INFO_TOP_DIR)
+        except OSError:
+            pass
diff --git a/install/tools/ipa-compat-manage b/install/tools/ipa-compat-manage
index 13a93cbed02ca69f4f6e8cb156a2f6f18e2da899..f7564e0c59fd2b310bc15de1ac0ffdb80217fe9b 100755
--- a/install/tools/ipa-compat-manage
+++ b/install/tools/ipa-compat-manage
@@ -196,24 +196,5 @@ def main():
 
     return retval
 
-try:
-    if __name__ == "__main__":
-        sys.exit(main())
-except BadSyntax, e:
-    print "There is a syntax error in this update file:"
-    print "  %s" % e
-    sys.exit(1)
-except RuntimeError, e:
-    print "%s" % e
-    sys.exit(1)
-except SystemExit, e:
-    sys.exit(e)
-except KeyboardInterrupt, e:
-    sys.exit(1)
-except config.IPAConfigError, e:
-    print "An IPA server to update cannot be found. Has one been configured yet?"
-    print "The error was: %s" % e
-    sys.exit(1)
-except errors.LDAPError, e:
-    print "An error occurred while performing operations: %s" % e
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-compat-manage')
diff --git a/install/tools/ipa-compliance b/install/tools/ipa-compliance
index 8ae91b7779295408d5227f813f35b3885b55b842..c1839ff7f782632d253d9726324021734e849c6a 100644
--- a/install/tools/ipa-compliance
+++ b/install/tools/ipa-compliance
@@ -166,6 +166,9 @@ def check_compliance(tmpdir, debug=False):
             print 'IPA is in compliance: %d of %d entitlements used.' % (hostcount, available)
 
 def main():
+    if os.geteuid() != 0:
+        sys.exit("\nMust be root to check compliance\n")
+
     installutils.check_server_configuration()
 
     if not os.path.exists('/etc/ipa/default.conf'):
@@ -189,12 +192,5 @@ def main():
 
     return 0
 
-try:
-    if not os.geteuid()==0:
-        sys.exit("\nMust be root to check compliance\n")
-
-    main()
-except SystemExit, e:
-    sys.exit(e)
-except RuntimeError, e:
-    sys.exit(e)
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-compliance')
diff --git a/install/tools/ipa-csreplica-manage b/install/tools/ipa-csreplica-manage
index 97c504552c0763e351ef6ae7e197a0acb684a83b..44d5087f77498df4dd92f2aa03500958e7806da5 100755
--- a/install/tools/ipa-csreplica-manage
+++ b/install/tools/ipa-csreplica-manage
@@ -438,19 +438,5 @@ def main():
             replica2 = args[1]
         del_link(realm, replica1, replica2, dirman_passwd)
 
-try:
-    main()
-except KeyboardInterrupt:
-    sys.exit(1)
-except SystemExit, e:
-    sys.exit(e)
-except ldap.INVALID_CREDENTIALS:
-    sys.exit("Invalid password")
-except ldap.INSUFFICIENT_ACCESS:
-    sys.exit("Insufficient access")
-except ldap.LOCAL_ERROR, e:
-    sys.exit(convert_error(e))
-except ldap.SERVER_DOWN, e:
-    sys.exit("%s" % convert_error(e))
-except Exception, e:
-    sys.exit("unexpected error: %s" % convert_error(e))
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-replica-manage')
diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
index b540630f4f2782603c31ce1905870c38c9af98ab..28e622dec85d9edd1f74548e95f95be0f6d70c33 100755
--- a/install/tools/ipa-dns-install
+++ b/install/tools/ipa-dns-install
@@ -19,8 +19,6 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-import traceback
-
 from ipaserver.plugins.ldap2 import ldap2
 from ipaserver.install import service, bindinstance, ntpinstance, httpinstance
 from ipaserver.install.installutils import *
@@ -34,6 +32,8 @@ import krbV
 import ldap
 from ipapython.ipa_log_manager import *
 
+log_file_name = "/var/log/ipaserver-install.log"
+
 def parse_options():
     parser = IPAOptionParser(version=version.VERSION)
     parser.add_option("-p", "--ds-password", dest="dm_password",
@@ -89,8 +89,8 @@ def main():
     if os.getegid() != 0:
         sys.exit("Must be root to setup server")
 
-    standard_logging_setup("/var/log/ipaserver-install.log", debug=options.debug, filemode='a')
-    print "\nThe log file for this installation can be found in /var/log/ipaserver-install.log"
+    standard_logging_setup(log_file_name, debug=options.debug, filemode='a')
+    print "\nThe log file for this installation can be found in %s" % log_file_name
 
     root_logger.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
     root_logger.debug("missing options might be asked for interactively later\n")
@@ -243,26 +243,6 @@ def main():
 
     return 0
 
-try:
-    sys.exit(main())
-except SystemExit, e:
-    sys.exit(e)
-except KeyboardInterrupt:
-    print "Installation cancelled."
-except RuntimeError, e:
-    print str(e)
-except HostnameLocalhost:
-    print "The hostname resolves to the localhost address (127.0.0.1/::1)"
-    print "Please change your /etc/hosts file so that the hostname"
-    print "resolves to the ip address of your network interface."
-    print "The KDC service does not listen on localhost"
-    print ""
-    print "Please fix your /etc/hosts file and restart the setup program"
-except Exception, e:
-    message = "Unexpected error - see ipaserver-install.log for details:\n %s" % str(e)
-    print message
-    message = str(e)
-    for str in traceback.format_tb(sys.exc_info()[2]):
-        message = message + "\n" + str
-    root_logger.debug(message)
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, log_file_name=log_file_name,
+        operation_name='ipa-dns-install')
diff --git a/install/tools/ipa-ldap-updater b/install/tools/ipa-ldap-updater
index bd2233a94241c28375b29cc10d60908238b8f176..92883f1b88f73eedc8d1fe1be393d2984ca143dd 100755
--- a/install/tools/ipa-ldap-updater
+++ b/install/tools/ipa-ldap-updater
@@ -44,6 +44,8 @@ error was:
 """ % sys.exc_value
     sys.exit(1)
 
+log_file_name = '/var/log/ipaupgrade.log'
+
 def parse_options():
     usage = "%prog [options] input_file(s)\n"
     usage += "%prog [options]\n"
@@ -103,7 +105,7 @@ def main():
                 sys.exit("\nDirectory Manager password required")
 
     if options.upgrade:
-        standard_logging_setup('/var/log/ipaupgrade.log', verbose=True, debug=options.debug, filemode='a')
+        standard_logging_setup(log_file_name, verbose=True, debug=options.debug, filemode='a')
     else:
         standard_logging_setup(None, verbose=True, debug=options.debug)
 
@@ -154,16 +156,6 @@ def main():
         root_logger.info('Update complete')
         return 0
 
-try:
-    if __name__ == "__main__":
-        sys.exit(main())
-except BadSyntax, e:
-    print "There is a syntax error in this update file:"
-    print "  %s" % e
-    sys.exit(1)
-except RuntimeError, e:
-    sys.exit(e)
-except SystemExit, e:
-    sys.exit(e)
-except KeyboardInterrupt, e:
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, log_file_name=log_file_name,
+        operation_name='ipa-ldap-updater')
diff --git a/install/tools/ipa-managed-entries b/install/tools/ipa-managed-entries
index 00bb566226adf636fe1c2cfc4a6357636f3ffb71..b9a492e48d87ca72f7c0043c8a4a5a26b77be847 100755
--- a/install/tools/ipa-managed-entries
+++ b/install/tools/ipa-managed-entries
@@ -237,20 +237,5 @@ def main():
 
     return retval
 
-try:
-    if __name__ == "__main__":
-        sys.exit(main())
-except RuntimeError, e:
-    print "%s" % e
-    sys.exit(1)
-except SystemExit, e:
-    sys.exit(e)
-except KeyboardInterrupt, e:
-    sys.exit(1)
-except config.IPAConfigError, e:
-    print "An IPA server to update cannot be found. Has one been configured yet?"
-    print "The error was: %s" % e
-    sys.exit(1)
-except errors.LDAPError, e:
-    print "An error occurred while performing operations: %s" % e
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-managed-entries')
diff --git a/install/tools/ipa-nis-manage b/install/tools/ipa-nis-manage
index 5c5bbca8e0435441cbb2ea10d80245e36a86e9a7..1c6de7b57d61bc1ecb8f69833a4b76a9af45a618 100755
--- a/install/tools/ipa-nis-manage
+++ b/install/tools/ipa-nis-manage
@@ -200,24 +200,5 @@ def main():
 
     return retval
 
-try:
-    if __name__ == "__main__":
-        sys.exit(main())
-except BadSyntax, e:
-    print "There is a syntax error in this update file:"
-    print "  %s" % e
-    sys.exit(1)
-except RuntimeError, e:
-    print "%s" % e
-    sys.exit(1)
-except SystemExit, e:
-    sys.exit(e)
-except KeyboardInterrupt, e:
-    sys.exit(1)
-except config.IPAConfigError, e:
-    print "An IPA server to update cannot be found. Has one been configured yet?"
-    print "The error was: %s" % e
-    sys.exit(1)
-except errors.LDAPError, e:
-    print "An error occurred while performing operations: %s" % e
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-nis-manage')
diff --git a/install/tools/ipa-replica-conncheck b/install/tools/ipa-replica-conncheck
index 6ec3be2a919c4a8a8a32cbf76f54b12d6652ff5e..76428c8d200410d92ec85c474e6b4bb53315ed5e 100755
--- a/install/tools/ipa-replica-conncheck
+++ b/install/tools/ipa-replica-conncheck
@@ -386,16 +386,9 @@ def main():
             time.sleep(3600)
             print_info("Connection check timeout: terminating listening program")
 
-if __name__ == "__main__":
+if __name__ == '__main__':
     try:
-        sys.exit(main())
-    except SystemExit, e:
-        sys.exit(e)
-    except KeyboardInterrupt:
-        print_info("\nCleaning up...")
-        sys.exit(1)
-    except RuntimeError, e:
-        sys.exit(e)
+        installutils.run_script(main, operation_name='ipa-replica-conncheck')
     finally:
         clean_responders(RESPONDERS)
         for file_name in (CCACHE_FILE, KRB5_CONFIG):
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index 07b1781ee7f99cacf1a3abbd6207b95f38da1807..d491eed76783b343d418dfde44f8e5cbb3ded36a 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -21,7 +21,7 @@
 import sys
 import socket
 
-import os, pwd, traceback, shutil
+import os, pwd, shutil
 import grp
 from optparse import OptionGroup
 
@@ -43,8 +43,9 @@ from ipapython import sysrestore
 from ipapython import services as ipaservices
 from ipapython.ipa_log_manager import *
 
-CACERT="/etc/ipa/ca.crt"
-REPLICA_INFO_TOP_DIR=None
+log_file_name = "/var/log/ipareplica-install.log"
+CACERT = "/etc/ipa/ca.crt"
+REPLICA_INFO_TOP_DIR = None
 
 def parse_options():
     usage = "%prog [options] REPLICA_FILE"
@@ -277,7 +278,11 @@ def check_bind():
 
 def main():
     safe_options, options, filename = parse_options()
-    standard_logging_setup("/var/log/ipareplica-install.log", debug=options.debug)
+
+    if os.geteuid() != 0:
+        sys.exit("\nYou must be root to run this script.\n")
+
+    standard_logging_setup(log_file_name, debug=options.debug)
     root_logger.debug('%s was invoked with argument "%s" and options: %s' % (sys.argv[0], filename, safe_options))
 
     if not ipautil.file_exists(filename):
@@ -487,41 +492,20 @@ def main():
     #Everything installed properly, activate ipa service.
     ipaservices.knownservices.ipa.enable()
 
-try:
-    if not os.geteuid()==0:
-        sys.exit("\nYou must be root to run this script.\n")
+fail_message = '''
+Your system may be partly configured.
+Run /usr/sbin/ipa-server-install --uninstall to clean up.
+'''
 
-    main()
-    sys.exit(0)
-except SystemExit, e:
-    sys.exit(e)
-except socket.error, (errno, errstr):
-    print errstr
-except HostnameLocalhost:
-    print "The hostname resolves to the localhost address (127.0.0.1/::1)"
-    print "Please change your /etc/hosts file so that the hostname"
-    print "resolves to the ip address of your network interface."
-    print ""
-    print "Please fix your /etc/hosts file and restart the setup program"
-except Exception, e:
-    print "creation of replica failed: %s" % str(e)
-    message = str(e)
-    for str in traceback.format_tb(sys.exc_info()[2]):
-        message = message + "\n" + str
-    root_logger.debug(message)
-except KeyboardInterrupt:
-    print "Installation cancelled."
-finally:
-    # always try to remove decrypted replica file
+if __name__ == '__main__':
     try:
-        if REPLICA_INFO_TOP_DIR:
-            shutil.rmtree(REPLICA_INFO_TOP_DIR)
-    except OSError:
-        pass
-
-print ""
-print "Your system may be partly configured."
-print "Run /usr/sbin/ipa-server-install --uninstall to clean up."
-
-# the only way to get here is on error or ^C
-sys.exit(1)
+        installutils.run_script(main, log_file_name=log_file_name,
+                operation_name='ipa-replica-install',
+                fail_message=fail_message)
+    finally:
+        # always try to remove decrypted replica file
+        try:
+            if REPLICA_INFO_TOP_DIR:
+                shutil.rmtree(REPLICA_INFO_TOP_DIR)
+        except OSError:
+            pass
diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index f1f5425ca8d4083e7cb11f8d25f327ffb4ab2520..b388b31752811e286b20ad4301a852870c2ed5ec 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -21,7 +21,6 @@ import sys
 import os
 
 import ldap, re, krbV
-import traceback
 
 from ipapython import ipautil
 from ipaserver.install import replication, dsinstance, installutils
@@ -532,25 +531,5 @@ def main():
             replica2 = args[1]
         del_link(realm, replica1, replica2, dirman_passwd)
 
-try:
-    main()
-except KeyboardInterrupt:
-    sys.exit(1)
-except SystemExit, e:
-    sys.exit(e)
-except RuntimeError, e:
-    sys.exit(e)
-except ldap.INVALID_CREDENTIALS:
-    print "Invalid password"
-    sys.exit(1)
-except ldap.INSUFFICIENT_ACCESS:
-    print "Insufficient access"
-    sys.exit(1)
-except ldap.LOCAL_ERROR, e:
-    print e.args[0]['info']
-    sys.exit(1)
-except ldap.SERVER_DOWN, e:
-    print e.args[0]['desc']
-except Exception, e:
-    print "unexpected error: %s" % str(e)
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-replica-manage')
diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare
index c54aa62b8e0e49fcc30d1359423dfa8615cc9cfe..aa715c8fa1e5f7d963bf5218371c885f2b35c3c3 100755
--- a/install/tools/ipa-replica-prepare
+++ b/install/tools/ipa-replica-prepare
@@ -22,7 +22,6 @@ import sys
 
 import tempfile, shutil, os, pwd
 from ipapython.ipa_log_manager import *
-import traceback
 from ConfigParser import SafeConfigParser
 import krbV
 
@@ -229,6 +228,9 @@ def get_dirman_password():
     return installutils.read_password("Directory Manager (existing master)", confirm=False, validate=False)
 
 def main():
+    if os.geteuid() != 0:
+        sys.exit("\nYou must be root to run this script.\n")
+
     installutils.check_server_configuration()
     options, args = parse_options()
 
@@ -453,20 +455,5 @@ def main():
             add_reverse_zone(reverse_zone)
             add_ptr_rr(reverse_zone, ip_address, replica_fqdn)
 
-try:
-    if not os.geteuid()==0:
-        sys.exit("\nYou must be root to run this script.\n")
-
-    main()
-except SystemExit, e:
-    sys.exit(e)
-except RuntimeError, e:
-    sys.exit(e)
-except Exception, e:
-    print "preparation of replica failed: %s" % str(e)
-    message = str(e)
-    for str in traceback.format_tb(sys.exc_info()[2]):
-        message = message + "\n" + str
-    root_logger.debug(message)
-    print message
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-replica-prepare')
diff --git a/install/tools/ipa-server-certinstall b/install/tools/ipa-server-certinstall
index 901678b2e8e250ed7d460df326ff965e74d6167e..b4de8ce4958a8551d4b3d4530b85d73a15abfc47 100755
--- a/install/tools/ipa-server-certinstall
+++ b/install/tools/ipa-server-certinstall
@@ -120,6 +120,9 @@ def import_cert(dirname, pkcs12_fname, pkcs12_passwd, db_password):
     return server_cert
 
 def main():
+    if os.geteuid() != 0:
+        sys.exit("\nYou must be root to run this script.\n")
+
     installutils.check_server_configuration()
 
     options, pkcs12_fname = parse_options()
@@ -165,12 +168,5 @@ def main():
 
     return 0
 
-try:
-    if not os.geteuid()==0:
-        sys.exit("\nYou must be root to run this script.\n")
-
-    main()
-except SystemExit, e:
-    sys.exit(e)
-except RuntimeError, e:
-    sys.exit(e)
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-server-certinstall')
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 1dd02ba870a02e902c4c345d9f5802ef09f78a7a..65cc77c25d182469bb9029f91fdae39e5b12e36f 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -34,7 +34,6 @@ import subprocess
 import signal
 import shutil
 import glob
-import traceback
 import pickle
 import random
 import tempfile
@@ -50,7 +49,7 @@ from ipaserver.install import certs
 from ipaserver.install import cainstance
 from ipaserver.install import memcacheinstance
 
-from ipaserver.install import service
+from ipaserver.install import service, installutils
 from ipapython import version
 from ipaserver.install.installutils import *
 from ipaserver.plugins.ldap2 import ldap2
@@ -1094,37 +1093,29 @@ def main():
         os.remove(ANSWER_CACHE)
     return 0
 
-try:
-    success = True
+if __name__ == '__main__':
     try:
-        rval = main()
-        if rval != 0:
-            success = False
-        sys.exit(rval)
-    except SystemExit, e:
-        if e.code is not None or e.code != 0:
-            success = False
-        sys.exit(e)
-    except Exception, e:
+        # FIXME: Common option parsing, logging setup, etc should be factored
+        # out from all install scripts
+        safe_options, options = parse_options()
+        if options.uninstall:
+            log_file_name = "/var/log/ipaserver-uninstall.log"
+        else:
+            log_file_name = "/var/log/ipaserver-install.log"
+
         success = False
-        if uninstalling:
-            message = "Unexpected error - see ipaserver-uninstall.log for details:\n %s" % str(e)
-        else:
-            message = "Unexpected error - see ipaserver-install.log for details:\n %s" % str(e)
-        print message
-        message = str(e)
-        for str in traceback.format_tb(sys.exc_info()[2]):
-            message = message + "\n" + str
-        root_logger.debug(message)
-        sys.exit(1)
-finally:
-    if pw_name and ipautil.file_exists(pw_name):
-        os.remove(pw_name)
+        installutils.run_script(main, log_file_name=log_file_name,
+                operation_name='ipa-server-install')
+        success = True
 
-    if not success and installation_cleanup:
-        # Do a cautious clean up as we don't know what failed and what is
-        # the state of the environment
-        try:
-            fstore.restore_file('/etc/hosts')
-        except:
-            pass
+    finally:
+        if pw_name and ipautil.file_exists(pw_name):
+            os.remove(pw_name)
+
+        if not success and installation_cleanup:
+            # Do a cautious clean up as we don't know what failed and what is
+            # the state of the environment
+            try:
+                fstore.restore_file('/etc/hosts')
+            except:
+                pass
diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
index a2a30249923ed127d2d68d312ad7abeb04627678..0cf59f293b6a35a7b4fddda14a729413ab51e17f 100644
--- a/install/tools/ipa-upgradeconfig
+++ b/install/tools/ipa-upgradeconfig
@@ -305,10 +305,5 @@ def main():
     cleanup_kdc(fstore)
     upgrade_ipa_profile(krbctx.default_realm)
 
-try:
-    if __name__ == "__main__":
-        sys.exit(main())
-except SystemExit, e:
-    sys.exit(e)
-except KeyboardInterrupt, e:
-    sys.exit(1)
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipa-upgradeconfig')
diff --git a/install/tools/ipactl b/install/tools/ipactl
index 74ee383047618ac3053d61d40a8eb13e27f7fc78..c4d26b8df150119e0bc84abac020f8989a2a8ad2 100755
--- a/install/tools/ipactl
+++ b/install/tools/ipactl
@@ -21,10 +21,10 @@
 import sys
 try:
     import os
-    from ipaserver.install import service
+    from ipaserver.install import service, installutils
     from ipapython import services as ipaservices
     from ipaserver.install.dsinstance import config_dirname, realm_to_serverid
-    from ipaserver.install.installutils import is_ipa_configured, wait_for_open_ports, wait_for_open_socket
+    from ipaserver.install.installutils import is_ipa_configured, wait_for_open_ports, wait_for_open_socket, ScriptError
     from ipapython import sysrestore
     from ipapython import config
     from ipalib import api, errors
@@ -44,13 +44,8 @@ error was:
 
 SASL_EXTERNAL = ldap.sasl.sasl({}, 'EXTERNAL')
 
-class IpactlError(StandardError):
-    def __init__(self, msg = '', rval = 1):
-        self.msg = msg
-        self.rval = rval
-
-    def __str__(self):
-        return self.msg
+class IpactlError(ScriptError):
+    pass
 
 def check_IPA_configuration():
     if not is_ipa_configured():
@@ -386,17 +381,6 @@ def main():
     elif args[0].lower() == "status":
         ipa_status(options)
 
-try:
-    if __name__ == "__main__":
-        sys.exit(main())
-except IpactlError, e:
-    if e.msg:
-        emit_err(e.msg)
-    sys.exit(e.rval)
-except RuntimeError, e:
-    emit_err("%s" % e)
-    sys.exit(1)
-except SystemExit, e:
-    sys.exit(e)
-except KeyboardInterrupt, e:
-    sys.exit(1)
+
+if __name__ == '__main__':
+    installutils.run_script(main, operation_name='ipactl')
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index 3e7ae41b5fdbc11353e43a63424f19fbc331435a..f02afc0861776a1d884f6141ec5dc7dc093e6695 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -31,10 +31,14 @@
 import tempfile
 import shutil
 from ConfigParser import SafeConfigParser
+import traceback
 
+import ldap
 from ipapython import ipautil, dnsclient, sysrestore
 from ipapython.ipa_log_manager import *
 from ipalib.util import validate_hostname
+from ipapython import config
+from ipalib import errors
 
 # Used to determine install status
 IPA_MODULES = ['httpd', 'kadmin', 'dirsrv', 'pki-cad', 'pkids', 'install', 'krb5kdc', 'ntpd', 'named', 'ipa_memcached']
@@ -54,6 +58,18 @@ class HostReverseLookupError(HostLookupError):
 class HostnameLocalhost(HostLookupError):
     pass
 
+
+class ScriptError(StandardError):
+    """An exception that records an error message and a return value
+    """
+    def __init__(self, msg = '', rval = 1):
+        self.msg = msg
+        self.rval = rval
+
+    def __str__(self):
+        return self.msg
+
+
 class ReplicaConfig:
     def __init__(self):
         self.realm_name = ""
@@ -712,3 +728,114 @@ def is_ipa_configured():
         root_logger.debug('filestore is tracking no files')
 
     return installed
+
+
+def run_script(main_function, operation_name, log_file_name=None,
+        fail_message=None):
+    """Run the given function as a command-line utility
+
+    This function:
+
+    - Runs the given function
+    - Formats any errors
+    - Exits with the appropriate code
+
+    :param main_function: Function to call
+    :param log_file_name: Name of the log file (displayed on unexpected errors)
+    :param operation_name: Name of the script
+    :param fail_message: Optional message displayed on failure
+    """
+
+    root_logger.info('Starting script: %s', operation_name)
+    try:
+        try:
+            return_value = main_function()
+        except BaseException, e:
+            if isinstance(e, SystemExit) and (e.code is None or e.code == 0):
+                # Not an error after all
+                root_logger.info('The %s command was successful',
+                    operation_name)
+            else:
+                # Log at the INFO level, which is not output to the console
+                # (unless in debug/verbose mode), but is written to a logfile
+                # if one is open.
+                tb = sys.exc_info()[2]
+                root_logger.info('\n'.join(traceback.format_tb(tb)))
+                root_logger.info('The %s command failed, exception: %s: %s',
+                    operation_name, type(e).__name__, e)
+                exception = e
+                if fail_message:
+                    print fail_message
+                raise
+        else:
+            if return_value:
+                root_logger.info('The %s command failed, return value %s',
+                    operation_name, return_value)
+            else:
+                root_logger.info('The %s command was successful',
+                    operation_name)
+            sys.exit(return_value)
+
+    except BaseException, error:
+        handle_error(error, log_file_name)
+
+
+def handle_error(error, log_file_name=None):
+    """Handle specific errors"""
+
+    if isinstance(error, SystemExit):
+        sys.exit(error)
+    if isinstance(error, RuntimeError):
+        sys.exit(error)
+    if isinstance(error, KeyboardInterrupt):
+        print >> sys.stderr, "Cancelled."
+        sys.exit(1)
+
+    if isinstance(error, ScriptError):
+        if error.msg:
+            print >> sys.stderr, error.msg
+        sys.exit(error.rval)
+
+    if isinstance(error, socket.error):
+        print >> sys.stderr, error
+        sys.exit(1)
+
+    if isinstance(error, ldap.INVALID_CREDENTIALS):
+        print >> sys.stderr, "Invalid password"
+        sys.exit(1)
+    if isinstance(error, ldap.INSUFFICIENT_ACCESS):
+        print >> sys.stderr, "Insufficient access"
+        sys.exit(1)
+    if isinstance(error, ldap.LOCAL_ERROR):
+        print >> sys.stderr, error.args[0]['info']
+        sys.exit(1)
+    if isinstance(error, ldap.SERVER_DOWN):
+        print >> sys.stderr, error.args[0]['desc']
+        sys.exit(1)
+    if isinstance(error, ldap.LDAPError):
+        print >> sys.stderr, 'LDAP error: %s' % type(error).__name__
+        print >> sys.stderr, error.args[0]['info']
+        sys.exit(1)
+
+    if isinstance(error, config.IPAConfigError):
+        print >> sys.stderr, "An IPA server to update cannot be found. Has one been configured yet?"
+        print >> sys.stderr, "The error was: %s" % error
+        sys.exit(1)
+    if isinstance(error, errors.LDAPError):
+        print >> sys.stderr, "An error occurred while performing operations: %s" % error
+        sys.exit(1)
+
+    if isinstance(error, HostnameLocalhost):
+        print >> sys.stderr, "The hostname resolves to the localhost address (127.0.0.1/::1)"
+        print >> sys.stderr, "Please change your /etc/hosts file so that the hostname"
+        print >> sys.stderr, "resolves to the ip address of your network interface."
+        print >> sys.stderr, ""
+        print >> sys.stderr, "Please fix your /etc/hosts file and restart the setup program"
+        sys.exit(1)
+
+    if log_file_name:
+        print >> sys.stderr, "Unexpected error - see %s for details:" % log_file_name
+    else:
+        print >> sys.stderr, "Unexpected error"
+    print >> sys.stderr, '%s: %s' % (type(error).__name__, error)
+    sys.exit(1)
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 90b3691a8595f952f9064d5cccb2523bd08426be..c16784182129beba98302096edd8edd073bea79b 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -47,9 +47,12 @@
 from ipaserver.install.plugins import PRE_UPDATE, POST_UPDATE
 from ipaserver.install.plugins import FIRST, MIDDLE, LAST
 
-class BadSyntax(Exception):
+class BadSyntax(installutils.ScriptError):
     def __init__(self, value):
         self.value = value
+        self.msg = "There is a syntax error in this update file: \n  %s" % value
+        self.rval = 1
+
     def __str__(self):
         return repr(self.value)
 
-- 
1.7.7.6

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

Reply via email to