0000-12-31 18:09:24 -05:50
# Authors: Simo Sorce <ssorce@redhat.com>
#
# Copyright (C) 2007 Red Hat
# see file 'COPYING' for use and warranty information
#
2010-12-09 06:59:11 -06:00
# 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.
0000-12-31 18:09:24 -05:50
#
# 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
2010-12-09 06:59:11 -06:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
0000-12-31 18:09:24 -05:50
#
import socket
import errno
import getpass
0000-12-31 18:09:24 -05:50
import os
import re
import fileinput
import sys
2008-03-03 15:10:06 -06:00
import struct
2008-03-27 14:33:06 -05:00
import fcntl
2010-12-01 10:22:56 -06:00
import netaddr
2011-03-14 11:56:17 -05:00
import time
2011-06-17 15:47:39 -05:00
import tempfile
2011-08-29 10:16:52 -05:00
import shutil
2012-05-31 07:34:09 -05:00
from ConfigParser import SafeConfigParser
import traceback
2012-05-11 07:38:09 -05:00
from dns import resolver , rdatatype
from dns . exception import DNSException
2012-05-31 07:34:09 -05:00
import ldap
2007-12-18 12:03:34 -06:00
2012-05-11 07:38:09 -05:00
from ipapython import ipautil , sysrestore
2011-11-15 13:39:31 -06:00
from ipapython . ipa_log_manager import *
2012-03-01 04:01:45 -06:00
from ipalib . util import validate_hostname
2012-05-31 07:34:09 -05:00
from ipapython import config
from ipalib import errors
0000-12-31 18:09:24 -05:50
2011-08-29 10:16:52 -05:00
# Used to determine install status
2012-02-15 15:55:59 -06:00
IPA_MODULES = [ ' httpd ' , ' kadmin ' , ' dirsrv ' , ' pki-cad ' , ' pkids ' , ' install ' , ' krb5kdc ' , ' ntpd ' , ' named ' , ' ipa_memcached ' ]
2011-08-29 10:16:52 -05:00
2011-10-06 04:26:03 -05:00
class BadHostError ( Exception ) :
pass
class HostLookupError ( BadHostError ) :
pass
class HostForwardLookupError ( HostLookupError ) :
pass
class HostReverseLookupError ( HostLookupError ) :
pass
class HostnameLocalhost ( HostLookupError ) :
2011-05-27 10:05:45 -05:00
pass
2012-05-31 07:34:09 -05:00
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
2011-06-17 15:47:39 -05:00
class ReplicaConfig :
def __init__ ( self ) :
self . realm_name = " "
self . domain_name = " "
self . master_host_name = " "
self . dirman_password = " "
self . host_name = " "
self . dir = " "
self . subject_base = " "
self . setup_ca = False
0000-12-31 18:09:24 -05:50
def get_fqdn ( ) :
fqdn = " "
try :
fqdn = socket . getfqdn ( )
except :
try :
fqdn = socket . gethostname ( )
except :
fqdn = " "
return fqdn
2008-03-06 12:17:28 -06:00
2011-10-07 07:23:20 -05:00
def verify_fqdn ( host_name , no_host_dns = False , local_hostname = True ) :
2011-09-26 04:34:16 -05:00
"""
2011-10-06 04:26:03 -05:00
Run fqdn checks for given host :
- test hostname format
- test that hostname is fully qualified
- test forward and reverse hostname DNS lookup
2011-09-26 04:34:16 -05:00
2011-10-06 04:26:03 -05:00
Raises ` BadHostError ` or derived Exceptions if there is an error
2011-09-26 04:34:16 -05:00
: param host_name : The host name to verify .
2011-10-06 04:26:03 -05:00
: param no_host_dns : If true , skip DNS resolution tests of the host name .
2011-10-07 07:23:20 -05:00
: param local_hostname : If true , run additional checks for local hostnames
2011-09-26 04:34:16 -05:00
"""
0000-12-31 18:09:24 -05:50
if len ( host_name . split ( " . " ) ) < 2 or host_name == " localhost.localdomain " :
2011-10-06 04:26:03 -05:00
raise BadHostError ( " Invalid hostname ' %s ' , must be fully-qualified. " % host_name )
0000-12-31 18:09:24 -05:50
2011-03-17 09:22:33 -05:00
if host_name != host_name . lower ( ) :
2011-10-06 04:26:03 -05:00
raise BadHostError ( " Invalid hostname ' %s ' , must be lower-case. " % host_name )
2011-03-17 09:22:33 -05:00
2011-07-25 10:14:01 -05:00
if ipautil . valid_ip ( host_name ) :
2011-10-06 04:26:03 -05:00
raise BadHostError ( " IP address not allowed as a hostname " )
2011-07-25 10:14:01 -05:00
2012-03-01 04:01:45 -06:00
try :
# make sure that the host name meets the requirements in ipalib
validate_hostname ( host_name )
except ValueError , e :
raise BadHostError ( " Invalid hostname ' %s ' , %s " % ( host_name , unicode ( e ) ) )
2011-10-07 07:23:20 -05:00
if local_hostname :
try :
2012-05-11 07:38:09 -05:00
root_logger . debug ( ' Check if %s is a primary hostname for localhost ' , host_name )
2011-10-07 07:23:20 -05:00
ex_name = socket . gethostbyaddr ( host_name )
2012-05-11 07:38:09 -05:00
root_logger . debug ( ' Primary hostname for localhost: %s ' , ex_name [ 0 ] )
2011-10-07 07:23:20 -05:00
if host_name != ex_name [ 0 ] :
raise HostLookupError ( " The host name %s does not match the primary host name %s . " \
" Please check /etc/hosts or DNS name resolution " % ( host_name , ex_name [ 0 ] ) )
except socket . gaierror :
pass
2011-05-31 05:51:38 -05:00
if no_host_dns :
print " Warning: skipping DNS resolution of host " , host_name
return
2008-03-30 19:00:43 -05:00
try :
2012-05-11 07:38:09 -05:00
root_logger . debug ( ' Search DNS for %s ' , host_name )
2008-03-30 19:00:43 -05:00
hostaddr = socket . getaddrinfo ( host_name , None )
2012-05-11 07:38:09 -05:00
except Exception , e :
root_logger . debug ( ' Search failed: %s ' , e )
2011-10-06 04:26:03 -05:00
raise HostForwardLookupError ( " Unable to resolve host name, check /etc/hosts or DNS name resolution " )
2008-03-30 19:00:43 -05:00
if len ( hostaddr ) == 0 :
2011-10-06 04:26:03 -05:00
raise HostForwardLookupError ( " Unable to resolve host name, check /etc/hosts or DNS name resolution " )
2008-03-30 19:00:43 -05:00
2012-05-11 07:38:09 -05:00
# Verify this is NOT a CNAME
try :
root_logger . debug ( ' Check if %s is not a CNAME ' , host_name )
resolver . query ( host_name , rdatatype . CNAME )
raise HostReverseLookupError ( " The IPA Server Hostname cannot be a CNAME, only A and AAAA names are allowed. " )
except DNSException :
pass
# list of verified addresses to prevent multiple searches for the same address
verified = set ( )
2008-03-30 19:00:43 -05:00
for a in hostaddr :
2012-05-11 07:38:09 -05:00
address = a [ 4 ] [ 0 ]
if address in verified :
continue
if address == ' 127.0.0.1 ' or address == ' ::1 ' :
raise HostForwardLookupError ( " The IPA Server hostname must not resolve to localhost ( %s ). A routable IP address must be used. Check /etc/hosts to see if %s is an alias for %s " % ( address , host_name , address ) )
2008-03-30 19:00:43 -05:00
try :
2012-05-11 07:38:09 -05:00
root_logger . debug ( ' Check reverse address of %s ' , address )
revname = socket . gethostbyaddr ( address ) [ 0 ]
except Exception , e :
root_logger . debug ( ' Check failed: %s ' , e )
2011-10-06 04:26:03 -05:00
raise HostReverseLookupError ( " Unable to resolve the reverse ip address, check /etc/hosts or DNS name resolution " )
2012-05-11 07:38:09 -05:00
root_logger . debug ( ' Found reverse name: %s ' , revname )
2008-03-30 19:00:43 -05:00
if revname != host_name :
2011-10-06 04:26:03 -05:00
raise HostReverseLookupError ( " The host name %s does not match the reverse lookup %s " % ( host_name , revname ) )
2012-05-11 07:38:09 -05:00
verified . add ( address )
2008-03-06 12:17:28 -06:00
2011-10-13 05:15:41 -05:00
def record_in_hosts ( ip , host_name = None , file = " /etc/hosts " ) :
"""
Search record in / etc / hosts - static table lookup for hostnames
In case of match , returns a tuple of ip address and a list of
hostname aliases
When no record is matched , None is returned
: param ip : IP address
: param host_name : Optional hostname to search
: param file : Optional path to the lookup table
"""
2011-02-10 14:47:45 -06:00
hosts = open ( file , ' r ' ) . readlines ( )
for line in hosts :
2011-02-15 10:51:18 -06:00
line = line . rstrip ( ' \n ' )
fields = line . partition ( ' # ' ) [ 0 ] . split ( )
if len ( fields ) == 0 :
2011-02-10 14:47:45 -06:00
continue
2011-02-15 10:51:18 -06:00
try :
hosts_ip = fields [ 0 ]
names = fields [ 1 : ]
if hosts_ip != ip :
continue
2011-10-13 05:15:41 -05:00
if host_name is not None :
if host_name in names :
return ( hosts_ip , names )
else :
return None
return ( hosts_ip , names )
2011-02-15 10:51:18 -06:00
except IndexError :
print " Warning: Erroneous line ' %s ' in %s " % ( line , file )
continue
2011-02-10 14:47:45 -06:00
2011-10-13 05:15:41 -05:00
return None
2011-02-10 14:47:45 -06:00
def add_record_to_hosts ( ip , host_name , file = " /etc/hosts " ) :
hosts_fd = open ( file , ' r+ ' )
hosts_fd . seek ( 0 , 2 )
hosts_fd . write ( ip + ' \t ' + host_name + ' ' + host_name . split ( ' . ' ) [ 0 ] + ' \n ' )
hosts_fd . close ( )
2009-11-23 02:15:35 -06:00
def read_ip_address ( host_name , fstore ) :
while True :
ip = ipautil . user_input ( " Please provide the IP address to be used for this host name " , allow_empty = False )
2011-05-31 05:51:38 -05:00
try :
2011-07-18 06:36:47 -05:00
ip_parsed = ipautil . CheckedIPAddress ( ip , match_local = True )
2011-05-31 05:51:38 -05:00
except Exception , e :
print " Error: Invalid IP Address %s : %s " % ( ip , e )
continue
else :
2009-11-23 02:15:35 -06:00
break
2011-05-27 13:17:22 -05:00
return ip_parsed
2009-11-23 02:15:35 -06:00
def read_dns_forwarders ( ) :
addrs = [ ]
2010-04-06 12:47:21 -05:00
if ipautil . user_input ( " Do you want to configure DNS forwarders? " , True ) :
print " Enter the IP address of DNS forwarder to use, or press Enter to finish. "
2010-02-08 12:31:57 -06:00
while True :
ip = ipautil . user_input ( " Enter IP address for a DNS forwarder " ,
allow_empty = True )
if not ip :
break
2011-05-31 05:51:38 -05:00
try :
2011-07-18 06:36:47 -05:00
ip_parsed = ipautil . CheckedIPAddress ( ip , parse_netmask = False )
2011-05-31 05:51:38 -05:00
except Exception , e :
print " Error: Invalid IP Address %s : %s " % ( ip , e )
2010-04-06 12:47:21 -05:00
print " DNS forwarder %s not added " % ip
2010-02-08 12:31:57 -06:00
continue
print " DNS forwarder %s added " % ip
2011-05-27 13:17:22 -05:00
addrs . append ( str ( ip_parsed ) )
2009-11-23 02:15:35 -06:00
if not addrs :
print " No DNS forwarders configured "
return addrs
2008-09-12 19:34:25 -05:00
def get_password ( prompt ) :
if os . isatty ( sys . stdin . fileno ( ) ) :
return getpass . getpass ( prompt )
else :
return sys . stdin . readline ( ) . rstrip ( )
2011-09-26 01:27:01 -05:00
def _read_password_default_validator ( password ) :
if len ( password ) < 8 :
raise ValueError ( " Password must be at least 8 characters long " )
def read_password ( user , confirm = True , validate = True , retry = True , validator = _read_password_default_validator ) :
0000-12-31 18:09:24 -05:50
correct = False
2011-10-06 01:22:08 -05:00
pwd = None
try :
while not correct :
if not retry :
correct = True
pwd = get_password ( user + " password: " )
if not pwd :
2011-09-26 01:27:01 -05:00
continue
2011-10-06 01:22:08 -05:00
if validate :
try :
validator ( pwd )
except ValueError , e :
print str ( e )
pwd = None
continue
if not confirm :
correct = True
continue
pwd_confirm = get_password ( " Password (confirm): " )
if pwd != pwd_confirm :
print " Password mismatch! "
print " "
pwd = None
else :
correct = True
except EOFError :
return None
0000-12-31 18:09:24 -05:50
print " "
return pwd
0000-12-31 18:09:24 -05:50
def update_file ( filename , orig , subst ) :
if os . path . exists ( filename ) :
2011-02-10 21:13:42 -06:00
st = os . stat ( filename )
0000-12-31 18:09:24 -05:50
pattern = " %s " % re . escape ( orig )
p = re . compile ( pattern )
for line in fileinput . input ( filename , inplace = 1 ) :
if not p . search ( line ) :
sys . stdout . write ( line )
else :
sys . stdout . write ( p . sub ( subst , line ) )
fileinput . close ( )
2011-02-10 21:13:42 -06:00
os . chown ( filename , st . st_uid , st . st_gid ) # reset perms
0000-12-31 18:09:24 -05:50
return 0
else :
print " File %s doesn ' t exist. " % filename
return 1
2009-04-17 16:17:31 -05:00
def set_directive ( filename , directive , value , quotes = True , separator = ' ' ) :
2008-07-11 10:34:29 -05:00
""" Set a name/value pair directive in a configuration file.
2011-06-09 12:16:07 -05:00
A value of None means to drop the directive .
2008-07-11 10:34:29 -05:00
This has only been tested with nss . conf
"""
2009-04-17 16:17:31 -05:00
valueset = False
2011-02-10 21:13:42 -06:00
st = os . stat ( filename )
2008-07-11 10:34:29 -05:00
fd = open ( filename )
2009-08-11 16:08:09 -05:00
newfile = [ ]
2008-07-11 10:34:29 -05:00
for line in fd :
if directive in line :
2009-04-17 16:17:31 -05:00
valueset = True
2011-06-09 12:16:07 -05:00
if value is not None :
if quotes :
newfile . append ( ' %s %s " %s " \n ' % ( directive , separator , value ) )
else :
newfile . append ( ' %s %s %s \n ' % ( directive , separator , value ) )
2008-07-11 10:34:29 -05:00
else :
2009-08-11 16:08:09 -05:00
newfile . append ( line )
2008-07-11 10:34:29 -05:00
fd . close ( )
2009-04-17 16:17:31 -05:00
if not valueset :
2011-06-09 12:16:07 -05:00
if value is not None :
if quotes :
newfile . append ( ' %s %s " %s " \n ' % ( directive , separator , value ) )
else :
newfile . append ( ' %s %s %s \n ' % ( directive , separator , value ) )
2008-07-11 10:34:29 -05:00
fd = open ( filename , " w " )
2009-08-11 16:08:09 -05:00
fd . write ( " " . join ( newfile ) )
2008-07-11 10:34:29 -05:00
fd . close ( )
2011-02-10 21:13:42 -06:00
os . chown ( filename , st . st_uid , st . st_gid ) # reset perms
2008-07-11 10:34:29 -05:00
2009-08-11 16:08:09 -05:00
def get_directive ( filename , directive , separator = ' ' ) :
2009-04-17 16:17:31 -05:00
"""
A rather inefficient way to get a configuration directive .
"""
fd = open ( filename , " r " )
for line in fd :
if directive in line :
line = line . strip ( )
result = line . split ( separator , 1 ) [ 1 ]
result = result . strip ( ' " ' )
2010-05-27 10:58:31 -05:00
result = result . strip ( ' ' )
2009-04-17 16:17:31 -05:00
fd . close ( )
return result
fd . close ( )
return None
2007-12-18 12:03:34 -06:00
def kadmin ( command ) :
2011-06-08 16:21:23 -05:00
ipautil . run ( [ " kadmin.local " , " -q " , command ,
" -x " , " ipa-setup-override-restrictions " ] )
2007-12-18 12:03:34 -06:00
def kadmin_addprinc ( principal ) :
kadmin ( " addprinc -randkey " + principal )
def kadmin_modprinc ( principal , options ) :
kadmin ( " modprinc " + options + " " + principal )
def create_keytab ( path , principal ) :
try :
if ipautil . file_exists ( path ) :
os . remove ( path )
except os . error :
2011-11-15 13:39:31 -06:00
root_logger . critical ( " Failed to remove %s . " % path )
2007-12-18 12:03:34 -06:00
kadmin ( " ktadd -k " + path + " " + principal )
0000-12-31 18:09:24 -05:50
2011-05-27 10:05:45 -05:00
def resolve_host ( host_name ) :
try :
addrinfos = socket . getaddrinfo ( host_name , None ,
socket . AF_UNSPEC , socket . SOCK_STREAM )
2012-01-20 01:30:40 -06:00
ip_list = [ ]
2011-05-27 10:05:45 -05:00
for ai in addrinfos :
ip = ai [ 4 ] [ 0 ]
if ip == " 127.0.0.1 " or ip == " ::1 " :
raise HostnameLocalhost ( " The hostname resolves to the localhost address " )
2012-01-20 01:30:40 -06:00
ip_list . append ( ip )
return ip_list
except socket . error :
return [ ]
2011-06-17 15:47:39 -05:00
def get_host_name ( no_host_dns ) :
"""
Get the current FQDN from the socket and verify that it is valid .
no_host_dns is a boolean that determines whether we enforce that the
hostname is resolvable .
Will raise a RuntimeError on error , returns hostname on success
"""
hostname = get_fqdn ( )
verify_fqdn ( hostname , no_host_dns )
return hostname
2012-01-04 13:04:21 -06:00
def get_server_ip_address ( host_name , fstore , unattended , options ) :
# Check we have a public IP that is associated with the hostname
try :
hostaddr = resolve_host ( host_name )
except 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 , " The KDC service does not listen on localhost "
print >> sys . stderr , " "
print >> sys . stderr , " Please fix your /etc/hosts file and restart the setup program "
sys . exit ( 1 )
ip_add_to_hosts = False
2012-01-20 01:30:40 -06:00
if len ( hostaddr ) > 1 :
print >> sys . stderr , " The server hostname resolves to more than one address: "
for addr in hostaddr :
print >> sys . stderr , " %s " % addr
if options . ip_address :
if str ( options . ip_address ) not in hostaddr :
print >> sys . stderr , " Address passed in --ip-address did not match any resolved "
print >> sys . stderr , " address! "
sys . exit ( 1 )
print " Selected IP address: " , str ( options . ip_address )
ip = options . ip_address
else :
if unattended :
print >> sys . stderr , " Please use --ip-address option to specify the address "
sys . exit ( 1 )
else :
ip = read_ip_address ( host_name , fstore )
elif len ( hostaddr ) == 1 :
2012-05-16 15:38:01 -05:00
try :
ip = ipautil . CheckedIPAddress ( hostaddr [ 0 ] , match_local = True )
except ValueError , e :
sys . exit ( " Invalid IP Address %s for %s : %s " % ( hostaddr [ 0 ] , host_name , unicode ( e ) ) )
2012-01-04 13:04:21 -06:00
else :
# hostname is not resolvable
ip = options . ip_address
ip_add_to_hosts = True
if ip is None :
print " Unable to resolve IP address for host name "
if unattended :
sys . exit ( 1 )
if options . ip_address :
if options . ip_address != ip and not options . setup_dns :
print >> sys . stderr , " Error: the hostname resolves to an IP address that is different "
print >> sys . stderr , " from the one provided on the command line. Please fix your DNS "
print >> sys . stderr , " or /etc/hosts file and restart the installation. "
sys . exit ( 1 )
ip = options . ip_address
if ip is None :
ip = read_ip_address ( host_name , fstore )
root_logger . debug ( " read ip_address: %s \n " % str ( ip ) )
ip_address = str ( ip )
# check /etc/hosts sanity, add a record when needed
hosts_record = record_in_hosts ( ip_address )
if hosts_record is None :
if ip_add_to_hosts :
print " Adding [ " + ip_address + " " + host_name + " ] to your /etc/hosts file "
fstore . backup_file ( " /etc/hosts " )
add_record_to_hosts ( ip_address , host_name )
else :
primary_host = hosts_record [ 1 ] [ 0 ]
if primary_host != host_name :
print >> sys . stderr , " Error: there is already a record in /etc/hosts for IP address %s : " \
% ip_address
print >> sys . stderr , hosts_record [ 0 ] , " " . join ( hosts_record [ 1 ] )
print >> sys . stderr , " Chosen hostname %s does not match configured canonical hostname %s " \
% ( host_name , primary_host )
print >> sys . stderr , " Please fix your /etc/hosts file and restart the installation. "
sys . exit ( 1 )
return ip
2011-06-17 15:47:39 -05:00
def expand_replica_info ( filename , password ) :
"""
Decrypt and expand a replica installation file into a temporary
location . The caller is responsible to remove this directory .
"""
top_dir = tempfile . mkdtemp ( " ipa " )
tarfile = top_dir + " /files.tar "
dir = top_dir + " /realm_info "
ipautil . decrypt_file ( filename , tarfile , password , top_dir )
ipautil . run ( [ " tar " , " xf " , tarfile , " -C " , top_dir ] )
os . remove ( tarfile )
return top_dir , dir
def read_replica_info ( dir , rconfig ) :
"""
Read the contents of a replica installation file .
rconfig is a ReplicaConfig object
"""
filename = dir + " /realm_info "
fd = open ( filename )
config = SafeConfigParser ( )
config . readfp ( fd )
rconfig . realm_name = config . get ( " realm " , " realm_name " )
rconfig . master_host_name = config . get ( " realm " , " master_host_name " )
rconfig . domain_name = config . get ( " realm " , " domain_name " )
rconfig . host_name = config . get ( " realm " , " destination_host " )
rconfig . subject_base = config . get ( " realm " , " subject_base " )
2011-07-18 02:33:57 -05:00
def check_server_configuration ( ) :
"""
Check if IPA server is configured on the system .
This is done by checking if there are system restore ( uninstall ) files
present on the system . Note that this check can only be run with root
privileges .
When IPA is not configured , this function raises a RuntimeError exception .
Most convenient use case for the function is in install tools that require
configured IPA for its function .
"""
server_fstore = sysrestore . FileStore ( ' /var/lib/ipa/sysrestore ' )
if not server_fstore . has_files ( ) :
raise RuntimeError ( " IPA is not configured on this system. " )
2011-08-29 10:16:52 -05:00
def remove_file ( filename ) :
"""
Remove a file and log any exceptions raised .
"""
try :
if os . path . exists ( filename ) :
os . unlink ( filename )
except Exception , e :
2011-11-15 13:39:31 -06:00
root_logger . error ( ' Error removing %s : %s ' % ( filename , str ( e ) ) )
2011-08-29 10:16:52 -05:00
def rmtree ( path ) :
"""
Remove a directory structure and log any exceptions raised .
"""
try :
if os . path . exists ( path ) :
shutil . rmtree ( path )
except Exception , e :
2011-11-15 13:39:31 -06:00
root_logger . error ( ' Error removing %s : %s ' % ( path , str ( e ) ) )
2011-08-29 10:16:52 -05:00
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 ) :
2011-11-15 13:39:31 -06:00
root_logger . debug ( ' %s is configured ' % module )
2011-08-29 10:16:52 -05:00
installed = True
else :
2011-11-15 13:39:31 -06:00
root_logger . debug ( ' %s is not configured ' % module )
2011-08-29 10:16:52 -05:00
if fstore . has_files ( ) :
2011-11-15 13:39:31 -06:00
root_logger . debug ( ' filestore has files ' )
2011-08-29 10:16:52 -05:00
installed = True
else :
2011-11-15 13:39:31 -06:00
root_logger . debug ( ' filestore is tracking no files ' )
2011-08-29 10:16:52 -05:00
return installed
2012-05-31 07:34:09 -05:00
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 and not isinstance ( e , SystemExit ) :
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 )