Add common is_installed() fn, better uninstall logging, check for errors.

The installer and ipactl used two different methods to determine
whether IPA was configured, unify them.

When uninstalling report any thing that looks suspicious and warn
that a re-install may fail. This includes any remaining 389-ds instances
and any state or files that remains after all the module uninstallers
are complete.

Add wrappers for removing files and directories to log failures.

https://fedorahosted.org/freeipa/ticket/1715
This commit is contained in:
Rob Crittenden 2011-08-29 11:16:52 -04:00
parent 28e6d137af
commit 91c9e83209
4 changed files with 96 additions and 43 deletions

View File

@ -428,6 +428,8 @@ def check_dirsrv(unattended):
def uninstall(): def uninstall():
rv = 0
print "Shutting down all IPA services" print "Shutting down all IPA services"
try: try:
(stdout, stderr, rc) = run(["/usr/sbin/ipactl", "stop"], raiseonerr=False) (stdout, stderr, rc) = run(["/usr/sbin/ipactl", "stop"], raiseonerr=False)
@ -441,6 +443,7 @@ def uninstall():
logging.debug("ipa-client-install returned %d" % rc) logging.debug("ipa-client-install returned %d" % rc)
raise RuntimeError(stdout) raise RuntimeError(stdout)
except Exception, e: except Exception, e:
rv = 1
print "Uninstall of client side components failed!" print "Uninstall of client side components failed!"
print "ipa-client-install returned: " + str(e) print "ipa-client-install returned: " + str(e)
@ -474,12 +477,32 @@ def uninstall():
ipautil.run(["/usr/sbin/groupdel", dsinstance.DS_GROUP]) ipautil.run(["/usr/sbin/groupdel", dsinstance.DS_GROUP])
except ipautil.CalledProcessError, e: except ipautil.CalledProcessError, e:
logging.critical("failed to delete group %s" % e) logging.critical("failed to delete group %s" % e)
rv = 1
except KeyError: except KeyError:
logging.info("Group %s already removed", dsinstance.DS_GROUP) logging.info("Group %s already removed", dsinstance.DS_GROUP)
service.chkconfig_off('ipa') service.chkconfig_off('ipa')
return 0 # Now for some sanity checking. Make sure everything was really
# uninstalled.
serverids = dsinstance.check_existing_installation()
if len(serverids):
rv = 1
logging.error('IPA cannot be re-installed without removing existing 389-ds instance(s)')
if fstore.has_files():
logging.error('Some files have not been restored, see /var/lib/ipa/sysrestore/sysrestore.index')
has_state = False
for module in IPA_MODULES: # from installutils
if sstore.has_state(module):
logging.error('Some installation state for %s has not been restored, see /var/lib/ipa/sysrestore/sysrestore.state' % module)
has_state = True
rv = 1
if has_state:
logging.warn('Some installation state has not been restored.\nThis will cause re-installation to fail.\nIt should be safe to remove /var/lib/ipa/sysrestore.state but it may\nmean your system hasn\'t be restored to its pre-installation state.')
return rv
def set_subject_in_config(realm_name, dm_password, suffix, subject_base): def set_subject_in_config(realm_name, dm_password, suffix, subject_base):
@ -518,7 +541,7 @@ def main():
else: else:
standard_logging_setup("/var/log/ipaserver-install.log", options.debug) standard_logging_setup("/var/log/ipaserver-install.log", options.debug)
print "\nThe log file for this installation can be found in /var/log/ipaserver-install.log" print "\nThe log file for this installation can be found in /var/log/ipaserver-install.log"
if not options.external_ca and not options.external_cert_file and (dsinstance.DsInstance().is_configured() or cainstance.CADSInstance().is_configured()): if not options.external_ca and not options.external_cert_file and is_ipa_configured():
sys.exit("IPA server is already configured on this system.\n" sys.exit("IPA server is already configured on this system.\n"
+ "If you want to reinstall the IPA server please uninstall it first.") + "If you want to reinstall the IPA server please uninstall it first.")

View File

@ -23,6 +23,7 @@ try:
import os import os
from ipaserver.install import service from ipaserver.install import service
from ipaserver.install.dsinstance import config_dirname, realm_to_serverid from ipaserver.install.dsinstance import config_dirname, realm_to_serverid
from ipaserver.install.installutils import is_ipa_configured
from ipapython import sysrestore from ipapython import sysrestore
from ipapython import config from ipapython import config
from ipalib import api, errors from ipalib import api, errors
@ -51,7 +52,7 @@ class IpactlError(StandardError):
return self.msg return self.msg
def check_IPA_configuration(): def check_IPA_configuration():
if not sysrestore.FileStore('/var/lib/ipa/sysrestore').has_files(): if not is_ipa_configured():
# LSB status code 6: program is not configured # LSB status code 6: program is not configured
raise IpactlError("IPA is not configured " + raise IpactlError("IPA is not configured " +
"(see man pages of ipa-server-install for help)", 6) "(see man pages of ipa-server-install for help)", 6)

View File

@ -66,42 +66,24 @@ def schema_dirname(serverid):
return config_dirname(serverid) + "/schema/" return config_dirname(serverid) + "/schema/"
def erase_ds_instance_data(serverid): def erase_ds_instance_data(serverid):
try: installutils.rmtree("/etc/dirsrv/slapd-%s" % serverid)
shutil.rmtree("/etc/dirsrv/slapd-%s" % serverid)
except: installutils.rmtree("/usr/lib/dirsrv/slapd-%s" % serverid)
pass
try: installutils.rmtree("/usr/lib64/dirsrv/slapd-%s" % serverid)
shutil.rmtree("/usr/lib/dirsrv/slapd-%s" % serverid)
except: installutils.rmtree("/var/lib/dirsrv/slapd-%s" % serverid)
pass
try: installutils.rmtree("/var/lock/dirsrv/slapd-%s" % serverid)
shutil.rmtree("/usr/lib64/dirsrv/slapd-%s" % serverid)
except: installutils.remove_file("/var/run/slapd-%s.socket" % serverid)
pass
try: installutils.rmtree("/var/lib/dirsrv/scripts-%s" % serverid)
shutil.rmtree("/var/lib/dirsrv/slapd-%s" % serverid)
except: installutils.remove_file("/etc/dirsrv/ds.keytab")
pass
try: installutils.remove_file("/etc/sysconfig/dirsrv-%s" % serverid)
shutil.rmtree("/var/lock/dirsrv/slapd-%s" % serverid)
except:
pass
try:
os.unlink("/var/run/slapd-%s.socket" % serverid)
except:
pass
try:
shutil.rmtree("/var/lib/dirsrv/scripts-%s" % serverid)
except:
pass
try:
os.unlink("/etc/dirsrv/ds.keytab")
except:
pass
try:
os.unlink("/etc/sysconfig/dirsrv-%s" % serverid)
except:
pass
# try: # try:
# shutil.rmtree("/var/log/dirsrv/slapd-%s" % serverid) # shutil.rmtree("/var/log/dirsrv/slapd-%s" % serverid)
# except: # except:
@ -114,6 +96,7 @@ def check_existing_installation():
serverids = [] serverids = []
for d in dirs: for d in dirs:
logging.debug('Found existing 389-ds instance %s' % d)
serverids.append(os.path.basename(d).split("slapd-", 1)[1]) serverids.append(os.path.basename(d).split("slapd-", 1)[1])
return serverids return serverids
@ -672,10 +655,7 @@ class DsInstance(service.Service):
if user_exists == False: if user_exists == False:
pent = pwd.getpwnam(DS_USER) pent = pwd.getpwnam(DS_USER)
try: installutils.remove_file("/var/tmp/ldap_%d" % pent.pw_uid)
os.unlink("/var/tmp/ldap_%d" % pent.pw_uid)
except:
pass
try: try:
ipautil.run(["/usr/sbin/userdel", DS_USER]) ipautil.run(["/usr/sbin/userdel", DS_USER])
except ipautil.CalledProcessError, e: except ipautil.CalledProcessError, e:

View File

@ -30,10 +30,14 @@ import fcntl
import netaddr import netaddr
import time import time
import tempfile import tempfile
import shutil
from ConfigParser import SafeConfigParser from ConfigParser import SafeConfigParser
from ipapython import ipautil, dnsclient, sysrestore from ipapython import ipautil, dnsclient, sysrestore
# Used to determine install status
IPA_MODULES = ['httpd', 'ipa_kpasswd', 'dirsrv', 'pki-cad', 'pkids', 'install', 'krb5kdc', 'ntpd', 'named']
class HostnameLocalhost(Exception): class HostnameLocalhost(Exception):
pass pass
@ -508,3 +512,48 @@ def check_server_configuration():
server_fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore') server_fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
if not server_fstore.has_files(): if not server_fstore.has_files():
raise RuntimeError("IPA is not configured on this system.") raise RuntimeError("IPA is not configured on this system.")
def remove_file(filename):
"""
Remove a file and log any exceptions raised.
"""
try:
if os.path.exists(filename):
os.unlink(filename)
except Exception, e:
logging.error('Error removing %s: %s' % (filename, str(e)))
def rmtree(path):
"""
Remove a directory structure and log any exceptions raised.
"""
try:
if os.path.exists(path):
shutil.rmtree(path)
except Exception, e:
logging.error('Error removing %s: %s' % (path, str(e)))
def is_ipa_configured():
"""
Using the state and index install files determine if IPA is already
configured.
"""
installed = False
sstore = sysrestore.StateFile('/var/lib/ipa/sysrestore')
fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
for module in IPA_MODULES:
if sstore.has_state(module):
logging.debug('%s is configured' % module)
installed = True
else:
logging.debug('%s is not configured' % module)
if fstore.has_files():
logging.debug('filestore has files')
installed = True
else:
logging.debug('filestore is tracking no files')
return installed