Imported Debian patch 4.0.5-6~numeezy
This commit is contained in:
committed by
Mario Fetka
parent
c44de33144
commit
10dfc9587b
@@ -23,37 +23,25 @@ import shutil
|
||||
import tempfile
|
||||
import time
|
||||
import pwd
|
||||
import ldif
|
||||
import itertools
|
||||
import locale
|
||||
|
||||
from six.moves.configparser import SafeConfigParser
|
||||
import six
|
||||
from ConfigParser import SafeConfigParser
|
||||
|
||||
from ipalib import api, errors
|
||||
from ipalib.constants import FQDN
|
||||
from ipapython import version, ipautil, certdb
|
||||
from ipapython import version
|
||||
from ipapython.ipautil import run, user_input
|
||||
from ipapython import admintool
|
||||
from ipapython.dn import DN
|
||||
from ipaserver.install.dsinstance import create_ds_user
|
||||
from ipaserver.install.cainstance import create_ca_user
|
||||
from ipaserver.install.dsinstance import (realm_to_serverid, create_ds_group,
|
||||
create_ds_user, DS_USER)
|
||||
from ipaserver.install.cainstance import PKI_USER
|
||||
from ipaserver.install.replication import (wait_for_task, ReplicationManager,
|
||||
get_cs_replication_manager)
|
||||
from ipaserver.install import installutils
|
||||
from ipaserver.install import dsinstance, httpinstance, cainstance
|
||||
from ipapython import ipaldap
|
||||
import ipapython.errors
|
||||
from ipaplatform.constants import constants
|
||||
from ipaplatform.tasks import tasks
|
||||
from ipaserver.install.ipa_backup import BACKUP_DIR
|
||||
from ipaplatform import services
|
||||
from ipaplatform.paths import paths
|
||||
|
||||
try:
|
||||
from ipaserver.install import adtrustinstance
|
||||
except ImportError:
|
||||
adtrustinstance = None
|
||||
|
||||
|
||||
def recursive_chown(path, uid, gid):
|
||||
'''
|
||||
@@ -62,10 +50,10 @@ def recursive_chown(path, uid, gid):
|
||||
for root, dirs, files in os.walk(path):
|
||||
for dir in dirs:
|
||||
os.chown(os.path.join(root, dir), uid, gid)
|
||||
os.chmod(os.path.join(root, dir), 0o750)
|
||||
os.chmod(os.path.join(root, dir), 0750)
|
||||
for file in files:
|
||||
os.chown(os.path.join(root, file), uid, gid)
|
||||
os.chmod(os.path.join(root, file), 0o640)
|
||||
os.chmod(os.path.join(root, file), 0640)
|
||||
|
||||
|
||||
def decrypt_file(tmpdir, filename, keyring):
|
||||
@@ -92,39 +80,13 @@ def decrypt_file(tmpdir, filename, keyring):
|
||||
args.append('-d')
|
||||
args.append(source)
|
||||
|
||||
result = run(args, raiseonerr=False)
|
||||
if result.returncode != 0:
|
||||
raise admintool.ScriptError('gpg failed: %s' % result.error_log)
|
||||
(stdout, stderr, rc) = run(args, raiseonerr=False)
|
||||
if rc != 0:
|
||||
raise admintool.ScriptError('gpg failed: %s' % stderr)
|
||||
|
||||
return dest
|
||||
|
||||
|
||||
class RemoveRUVParser(ldif.LDIFParser):
|
||||
def __init__(self, input_file, writer, logger):
|
||||
ldif.LDIFParser.__init__(self, input_file)
|
||||
self.writer = writer
|
||||
self.log = logger
|
||||
|
||||
def handle(self, dn, entry):
|
||||
objectclass = None
|
||||
nsuniqueid = None
|
||||
|
||||
for name, value in entry.items():
|
||||
name = name.lower()
|
||||
if name == 'objectclass':
|
||||
objectclass = [x.lower() for x in value]
|
||||
elif name == 'nsuniqueid':
|
||||
nsuniqueid = [x.lower() for x in value]
|
||||
|
||||
if (objectclass and nsuniqueid and
|
||||
'nstombstone' in objectclass and
|
||||
'ffffffff-ffffffff-ffffffff-ffffffff' in nsuniqueid):
|
||||
self.log.debug("Removing RUV entry %s", dn)
|
||||
return
|
||||
|
||||
self.writer.unparse(dn, entry)
|
||||
|
||||
|
||||
class Restore(admintool.AdminTool):
|
||||
command_name = 'ipa-restore'
|
||||
log_file_name = paths.IPARESTORE_LOG
|
||||
@@ -133,14 +95,6 @@ class Restore(admintool.AdminTool):
|
||||
|
||||
description = "Restore IPA files and databases."
|
||||
|
||||
# directories and files listed here will be removed from filesystem before
|
||||
# files from backup are copied
|
||||
DIRS_TO_BE_REMOVED = [
|
||||
paths.DNSSEC_TOKENS_DIR,
|
||||
]
|
||||
|
||||
FILES_TO_BE_REMOVED = []
|
||||
|
||||
def __init__(self, options, args):
|
||||
super(Restore, self).__init__(options, args)
|
||||
self._conn = None
|
||||
@@ -173,25 +127,29 @@ class Restore(admintool.AdminTool):
|
||||
|
||||
|
||||
def validate_options(self):
|
||||
parser = self.option_parser
|
||||
options = self.options
|
||||
super(Restore, self).validate_options(needs_root=True)
|
||||
if options.data_only:
|
||||
installutils.check_server_configuration()
|
||||
|
||||
if len(self.args) < 1:
|
||||
parser.error("must provide the backup to restore")
|
||||
self.option_parser.error(
|
||||
"must provide the backup to restore")
|
||||
elif len(self.args) > 1:
|
||||
parser.error("must provide exactly one name for the backup")
|
||||
self.option_parser.error(
|
||||
"must provide exactly one name for the backup")
|
||||
|
||||
dirname = self.args[0]
|
||||
if not os.path.isabs(dirname):
|
||||
dirname = os.path.join(paths.IPA_BACKUP_DIR, dirname)
|
||||
if not os.path.isdir(dirname):
|
||||
parser.error("must provide path to backup directory")
|
||||
self.backup_dir = os.path.join(BACKUP_DIR, dirname)
|
||||
else:
|
||||
self.backup_dir = dirname
|
||||
|
||||
if options.gpg_keyring:
|
||||
if (not os.path.exists(options.gpg_keyring + '.pub') or
|
||||
not os.path.exists(options.gpg_keyring + '.sec')):
|
||||
parser.error("no such key %s" % options.gpg_keyring)
|
||||
not os.path.exists(options.gpg_keyring + '.sec')):
|
||||
raise admintool.ScriptError('No such key %s' %
|
||||
options.gpg_keyring)
|
||||
|
||||
|
||||
def ask_for_options(self):
|
||||
@@ -214,134 +172,65 @@ class Restore(admintool.AdminTool):
|
||||
options = self.options
|
||||
super(Restore, self).run()
|
||||
|
||||
self.backup_dir = self.args[0]
|
||||
if not os.path.isabs(self.backup_dir):
|
||||
self.backup_dir = os.path.join(paths.IPA_BACKUP_DIR, self.backup_dir)
|
||||
api.bootstrap(in_server=False, context='restore')
|
||||
api.finalize()
|
||||
|
||||
self.log.info("Preparing restore from %s on %s",
|
||||
self.backup_dir, FQDN)
|
||||
self.backup_dir, api.env.host)
|
||||
|
||||
self.header = os.path.join(self.backup_dir, 'header')
|
||||
|
||||
try:
|
||||
self.read_header()
|
||||
except IOError as e:
|
||||
raise admintool.ScriptError("Cannot read backup metadata: %s" % e)
|
||||
|
||||
if options.data_only:
|
||||
restore_type = 'DATA'
|
||||
if not options.instance:
|
||||
instances = []
|
||||
for instance in [realm_to_serverid(api.env.realm), 'PKI-IPA']:
|
||||
if os.path.exists(paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE % instance):
|
||||
instances.append(instance)
|
||||
else:
|
||||
restore_type = self.backup_type
|
||||
|
||||
# These checks would normally be in the validate method but
|
||||
# we need to know the type of backup we're dealing with.
|
||||
if restore_type == 'FULL':
|
||||
if options.online:
|
||||
raise admintool.ScriptError(
|
||||
"File restoration cannot be done online")
|
||||
if options.instance or options.backend:
|
||||
raise admintool.ScriptError(
|
||||
"Restore must be in data-only mode when restoring a "
|
||||
"specific instance or backend")
|
||||
else:
|
||||
installutils.check_server_configuration()
|
||||
|
||||
self.init_api()
|
||||
|
||||
if options.instance:
|
||||
instance_dir = (paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE %
|
||||
options.instance)
|
||||
if not os.path.exists(instance_dir):
|
||||
raise admintool.ScriptError(
|
||||
"Instance %s does not exist" % options.instance)
|
||||
|
||||
self.instances = [options.instance]
|
||||
|
||||
if options.backend:
|
||||
for instance in self.instances:
|
||||
db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
|
||||
(instance, options.backend))
|
||||
if os.path.exists(db_dir):
|
||||
break
|
||||
else:
|
||||
raise admintool.ScriptError(
|
||||
"Backend %s does not exist" % options.backend)
|
||||
|
||||
self.backends = [options.backend]
|
||||
|
||||
for instance, backend in itertools.product(self.instances,
|
||||
self.backends):
|
||||
db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
|
||||
(instance, backend))
|
||||
if os.path.exists(db_dir):
|
||||
break
|
||||
else:
|
||||
raise admintool.ScriptError(
|
||||
"Cannot restore a data backup into an empty system")
|
||||
|
||||
self.log.info("Performing %s restore from %s backup" %
|
||||
(restore_type, self.backup_type))
|
||||
|
||||
if self.backup_host != FQDN:
|
||||
raise admintool.ScriptError(
|
||||
"Host name %s does not match backup name %s" %
|
||||
(FQDN, self.backup_host))
|
||||
|
||||
if self.backup_ipa_version != str(version.VERSION):
|
||||
self.log.warning(
|
||||
"Restoring data from a different release of IPA.\n"
|
||||
"Data is version %s.\n"
|
||||
"Server is running %s." %
|
||||
(self.backup_ipa_version, str(version.VERSION)))
|
||||
if (not options.unattended and
|
||||
not user_input("Continue to restore?", False)):
|
||||
raise admintool.ScriptError("Aborted")
|
||||
instances = [options.instance]
|
||||
if options.data_only and not instances:
|
||||
raise admintool.ScriptError('No instances to restore to')
|
||||
|
||||
create_ds_group()
|
||||
create_ds_user()
|
||||
pent = pwd.getpwnam(constants.DS_USER)
|
||||
pent = pwd.getpwnam(DS_USER)
|
||||
|
||||
# Temporary directory for decrypting files before restoring
|
||||
self.top_dir = tempfile.mkdtemp("ipa")
|
||||
os.chown(self.top_dir, pent.pw_uid, pent.pw_gid)
|
||||
os.chmod(self.top_dir, 0o750)
|
||||
os.chmod(self.top_dir, 0750)
|
||||
self.dir = os.path.join(self.top_dir, "ipa")
|
||||
os.mkdir(self.dir)
|
||||
os.chmod(self.dir, 0o750)
|
||||
os.mkdir(self.dir, 0750)
|
||||
|
||||
os.chown(self.dir, pent.pw_uid, pent.pw_gid)
|
||||
|
||||
self.header = os.path.join(self.backup_dir, 'header')
|
||||
|
||||
cwd = os.getcwd()
|
||||
try:
|
||||
dirsrv = services.knownservices.dirsrv
|
||||
|
||||
self.extract_backup(options.gpg_keyring)
|
||||
|
||||
if restore_type == 'FULL':
|
||||
self.restore_default_conf()
|
||||
self.init_api(confdir=self.dir + paths.ETC_IPA)
|
||||
|
||||
databases = []
|
||||
for instance in self.instances:
|
||||
for backend in self.backends:
|
||||
database = (instance, backend)
|
||||
ldiffile = os.path.join(self.dir, '%s-%s.ldif' % database)
|
||||
if os.path.exists(ldiffile):
|
||||
databases.append(database)
|
||||
|
||||
if options.instance:
|
||||
for instance, backend in databases:
|
||||
if instance == options.instance:
|
||||
break
|
||||
else:
|
||||
raise admintool.ScriptError(
|
||||
"Instance %s not found in backup" % options.instance)
|
||||
|
||||
if options.backend:
|
||||
for instance, backend in databases:
|
||||
if backend == options.backend:
|
||||
break
|
||||
else:
|
||||
raise admintool.ScriptError(
|
||||
"Backend %s not found in backup" % options.backend)
|
||||
self.read_header()
|
||||
# These two checks would normally be in the validate method but
|
||||
# we need to know the type of backup we're dealing with.
|
||||
if (self.backup_type != 'FULL' and not options.data_only and
|
||||
not instances):
|
||||
raise admintool.ScriptError('Cannot restore a data backup into an empty system')
|
||||
if (self.backup_type == 'FULL' and not options.data_only and
|
||||
(options.instance or options.backend)):
|
||||
raise admintool.ScriptError('Restore must be in data-only mode when restoring a specific instance or backend.')
|
||||
if self.backup_host != api.env.host:
|
||||
self.log.warning('Host name %s does not match backup name %s' %
|
||||
(api.env.host, self.backup_host))
|
||||
if (not options.unattended and
|
||||
not user_input("Continue to restore?", False)):
|
||||
raise admintool.ScriptError("Aborted")
|
||||
if self.backup_ipa_version != str(version.VERSION):
|
||||
self.log.warning(
|
||||
"Restoring data from a different release of IPA.\n"
|
||||
"Data is version %s.\n"
|
||||
"Server is running %s." %
|
||||
(self.backup_ipa_version, str(version.VERSION)))
|
||||
if (not options.unattended and
|
||||
not user_input("Continue to restore?", False)):
|
||||
raise admintool.ScriptError("Aborted")
|
||||
|
||||
# Big fat warning
|
||||
if (not options.unattended and
|
||||
@@ -360,7 +249,8 @@ class Restore(admintool.AdminTool):
|
||||
self.log.info("Disabling all replication.")
|
||||
self.disable_agreements()
|
||||
|
||||
if restore_type != 'FULL':
|
||||
self.extract_backup(options.gpg_keyring)
|
||||
if options.data_only:
|
||||
if not options.online:
|
||||
self.log.info('Stopping Directory Server')
|
||||
dirsrv.stop(capture_output=False)
|
||||
@@ -369,41 +259,40 @@ class Restore(admintool.AdminTool):
|
||||
dirsrv.start(capture_output=False)
|
||||
else:
|
||||
self.log.info('Stopping IPA services')
|
||||
result = run(['ipactl', 'stop'], raiseonerr=False)
|
||||
if result.returncode not in [0, 6]:
|
||||
self.log.warn('Stopping IPA failed: %s' % result.error_log)
|
||||
(stdout, stderr, rc) = run(['ipactl', 'stop'], raiseonerr=False)
|
||||
if rc not in [0, 6]:
|
||||
self.log.warn('Stopping IPA failed: %s' % stderr)
|
||||
|
||||
self.restore_selinux_booleans()
|
||||
|
||||
http = httpinstance.HTTPInstance()
|
||||
|
||||
# We do either a full file restore or we restore data.
|
||||
if restore_type == 'FULL':
|
||||
self.remove_old_files()
|
||||
if 'CA' in self.backup_services:
|
||||
create_ca_user()
|
||||
self.cert_restore_prepare()
|
||||
if self.backup_type == 'FULL' and not options.data_only:
|
||||
if options.online:
|
||||
raise admintool.ScriptError('File restoration cannot be done online.')
|
||||
self.file_restore(options.no_logs)
|
||||
self.cert_restore()
|
||||
if 'CA' in self.backup_services:
|
||||
self.__create_dogtag_log_dirs()
|
||||
if http.is_kdcproxy_configured():
|
||||
httpinstance.create_kdcproxy_user()
|
||||
|
||||
# Always restore the data from ldif
|
||||
# We need to restore both userRoot and ipaca.
|
||||
for instance, backend in databases:
|
||||
self.ldif2db(instance, backend, online=options.online)
|
||||
# If we are restoring PKI-IPA then we need to restore the
|
||||
# userRoot backend in it and the main IPA instance. If we
|
||||
# have a unified instance we need to restore both userRoot and
|
||||
# ipaca.
|
||||
for instance in instances:
|
||||
if os.path.exists(paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE % instance):
|
||||
if options.backend is None:
|
||||
self.ldif2db(instance, 'userRoot', online=options.online)
|
||||
if os.path.exists(paths.IPACA_DIRSRV_INSTANCE_DB_TEMPLATE % instance):
|
||||
self.ldif2db(instance, 'ipaca', online=options.online)
|
||||
else:
|
||||
self.ldif2db(instance, options.backend, online=options.online)
|
||||
else:
|
||||
raise admintool.ScriptError('389-ds instance %s does not exist' % instance)
|
||||
|
||||
if restore_type != 'FULL':
|
||||
if options.data_only:
|
||||
if not options.online:
|
||||
self.log.info('Starting Directory Server')
|
||||
dirsrv.start(capture_output=False)
|
||||
else:
|
||||
# restore access controll configuration
|
||||
auth_backup_path = os.path.join(paths.VAR_LIB_IPA, 'auth_backup')
|
||||
if os.path.exists(auth_backup_path):
|
||||
tasks.restore_auth_configuration(auth_backup_path)
|
||||
# explicitly enable then disable the pki tomcatd service to
|
||||
# re-register its instance. FIXME, this is really wierd.
|
||||
services.knownservices.pki_tomcatd.enable()
|
||||
@@ -414,11 +303,10 @@ class Restore(admintool.AdminTool):
|
||||
self.log.info('Restarting SSSD')
|
||||
sssd = services.service('sssd')
|
||||
sssd.restart()
|
||||
http.remove_httpd_ccache()
|
||||
finally:
|
||||
try:
|
||||
os.chdir(cwd)
|
||||
except Exception as e:
|
||||
except Exception, e:
|
||||
self.log.error('Cannot change directory to %s: %s' % (cwd, e))
|
||||
shutil.rmtree(self.top_dir)
|
||||
|
||||
@@ -427,13 +315,6 @@ class Restore(admintool.AdminTool):
|
||||
'''
|
||||
Create an ldapi connection and bind to it using autobind as root.
|
||||
'''
|
||||
instance_name = installutils.realm_to_serverid(api.env.realm)
|
||||
|
||||
if not services.knownservices.dirsrv.is_running(instance_name):
|
||||
raise admintool.ScriptError(
|
||||
"directory server instance is not running/configured"
|
||||
)
|
||||
|
||||
if self._conn is not None:
|
||||
return self._conn
|
||||
|
||||
@@ -445,7 +326,7 @@ class Restore(admintool.AdminTool):
|
||||
try:
|
||||
pw_name = pwd.getpwuid(os.geteuid()).pw_name
|
||||
self._conn.do_external_bind(pw_name)
|
||||
except Exception as e:
|
||||
except Exception, e:
|
||||
raise admintool.ScriptError('Unable to bind to LDAP server: %s'
|
||||
% e)
|
||||
return self._conn
|
||||
@@ -459,14 +340,14 @@ class Restore(admintool.AdminTool):
|
||||
'''
|
||||
try:
|
||||
conn = self.get_connection()
|
||||
except Exception as e:
|
||||
except Exception, e :
|
||||
self.log.error('Unable to get connection, skipping disabling agreements: %s' % e)
|
||||
return
|
||||
masters = []
|
||||
dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
|
||||
try:
|
||||
entries = conn.get_entries(dn, conn.SCOPE_ONELEVEL)
|
||||
except Exception as e:
|
||||
except Exception, e:
|
||||
raise admintool.ScriptError(
|
||||
"Failed to read master data: %s" % e)
|
||||
else:
|
||||
@@ -479,9 +360,8 @@ class Restore(admintool.AdminTool):
|
||||
try:
|
||||
repl = ReplicationManager(api.env.realm, master,
|
||||
self.dirman_password)
|
||||
except Exception as e:
|
||||
except Exception, e:
|
||||
self.log.critical("Unable to disable agreement on %s: %s" % (master, e))
|
||||
continue
|
||||
|
||||
master_dn = DN(('cn', master), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
|
||||
try:
|
||||
@@ -504,9 +384,8 @@ class Restore(admintool.AdminTool):
|
||||
try:
|
||||
repl = get_cs_replication_manager(api.env.realm, master,
|
||||
self.dirman_password)
|
||||
except Exception as e:
|
||||
except Exception, e:
|
||||
self.log.critical("Unable to disable agreement on %s: %s" % (master, e))
|
||||
continue
|
||||
|
||||
host_entries = repl.find_ipa_replication_agreements()
|
||||
hosts = [rep.single_value.get('nsds5replicahost')
|
||||
@@ -529,23 +408,8 @@ class Restore(admintool.AdminTool):
|
||||
cn = time.strftime('import_%Y_%m_%d_%H_%M_%S')
|
||||
dn = DN(('cn', cn), ('cn', 'import'), ('cn', 'tasks'), ('cn', 'config'))
|
||||
|
||||
ldifdir = paths.SLAPD_INSTANCE_LDIF_DIR_TEMPLATE % instance
|
||||
ldifname = '%s-%s.ldif' % (instance, backend)
|
||||
ldiffile = os.path.join(ldifdir, ldifname)
|
||||
srcldiffile = os.path.join(self.dir, ldifname)
|
||||
|
||||
if not os.path.exists(ldifdir):
|
||||
pent = pwd.getpwnam(constants.DS_USER)
|
||||
os.mkdir(ldifdir)
|
||||
os.chmod(ldifdir, 0o770)
|
||||
os.chown(ldifdir, pent.pw_uid, pent.pw_gid)
|
||||
|
||||
ipautil.backup_file(ldiffile)
|
||||
with open(ldiffile, 'wb') as out_file:
|
||||
ldif_writer = ldif.LDIFWriter(out_file)
|
||||
with open(srcldiffile, 'rb') as in_file:
|
||||
ldif_parser = RemoveRUVParser(in_file, ldif_writer, self.log)
|
||||
ldif_parser.parse()
|
||||
ldiffile = os.path.join(self.dir, ldifname)
|
||||
|
||||
if online:
|
||||
conn = self.get_connection()
|
||||
@@ -562,25 +426,24 @@ class Restore(admintool.AdminTool):
|
||||
|
||||
try:
|
||||
conn.add_entry(ent)
|
||||
except Exception as e:
|
||||
self.log.error("Unable to bind to LDAP server: %s" % e)
|
||||
return
|
||||
except Exception, e:
|
||||
raise admintool.ScriptError(
|
||||
'Unable to bind to LDAP server: %s' % e)
|
||||
|
||||
self.log.info("Waiting for LDIF to finish")
|
||||
wait_for_task(conn, dn)
|
||||
else:
|
||||
try:
|
||||
os.makedirs(paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % instance)
|
||||
except OSError as e:
|
||||
pass
|
||||
|
||||
args = [paths.LDIF2DB,
|
||||
'-Z', instance,
|
||||
'-i', ldiffile,
|
||||
'-n', backend]
|
||||
result = run(args, raiseonerr=False)
|
||||
if result.returncode != 0:
|
||||
self.log.critical("ldif2db failed: %s" % result.error_log)
|
||||
args = ['%s/ldif2db' % self.__find_scripts_dir(instance),
|
||||
'-i', ldiffile]
|
||||
if backend is not None:
|
||||
args.append('-n')
|
||||
args.append(backend)
|
||||
else:
|
||||
args.append('-n')
|
||||
args.append('userRoot')
|
||||
(stdout, stderr, rc) = run(args, raiseonerr=False)
|
||||
if rc != 0:
|
||||
self.log.critical("ldif2db failed: %s" % stderr)
|
||||
|
||||
|
||||
def bak2db(self, instance, backend, online=True):
|
||||
@@ -593,7 +456,7 @@ class Restore(admintool.AdminTool):
|
||||
|
||||
instance here is a loaded term. It can mean either a separate
|
||||
389-ds install instance or a separate 389-ds backend. We only need
|
||||
to treat ipaca specially.
|
||||
to treat PKI-IPA and ipaca specially.
|
||||
'''
|
||||
if backend is not None:
|
||||
self.log.info('Restoring %s in %s' % (backend, instance))
|
||||
@@ -620,67 +483,23 @@ class Restore(admintool.AdminTool):
|
||||
|
||||
try:
|
||||
conn.add_entry(ent)
|
||||
except Exception as e:
|
||||
except Exception, e:
|
||||
raise admintool.ScriptError('Unable to bind to LDAP server: %s'
|
||||
% e)
|
||||
|
||||
self.log.info("Waiting for restore to finish")
|
||||
wait_for_task(conn, dn)
|
||||
else:
|
||||
args = [paths.BAK2DB,
|
||||
'-Z', instance,
|
||||
args = ['%s/bak2db' % self.__find_scripts_dir(instance),
|
||||
os.path.join(self.dir, instance)]
|
||||
if backend is not None:
|
||||
args.append('-n')
|
||||
args.append(backend)
|
||||
result = run(args, raiseonerr=False)
|
||||
if result.returncode != 0:
|
||||
self.log.critical("bak2db failed: %s" % result.error_log)
|
||||
(stdout, stderr, rc) = run(args, raiseonerr=False)
|
||||
if rc != 0:
|
||||
self.log.critical("bak2db failed: %s" % stderr)
|
||||
|
||||
|
||||
def restore_default_conf(self):
|
||||
'''
|
||||
Restore paths.IPA_DEFAULT_CONF to temporary directory.
|
||||
|
||||
Primary purpose of this method is to get cofiguration for api
|
||||
finalization when restoring ipa after uninstall.
|
||||
'''
|
||||
cwd = os.getcwd()
|
||||
os.chdir(self.dir)
|
||||
args = ['tar',
|
||||
'--xattrs',
|
||||
'--selinux',
|
||||
'-xzf',
|
||||
os.path.join(self.dir, 'files.tar'),
|
||||
paths.IPA_DEFAULT_CONF[1:],
|
||||
]
|
||||
|
||||
result = run(args, raiseonerr=False)
|
||||
if result.returncode != 0:
|
||||
self.log.critical('Restoring %s failed: %s' %
|
||||
(paths.IPA_DEFAULT_CONF, result.error_log))
|
||||
os.chdir(cwd)
|
||||
|
||||
def remove_old_files(self):
|
||||
"""
|
||||
Removes all directories, files or temporal files that should be
|
||||
removed before backup files are copied, to prevent errors.
|
||||
"""
|
||||
for d in self.DIRS_TO_BE_REMOVED:
|
||||
try:
|
||||
shutil.rmtree(d)
|
||||
except OSError as e:
|
||||
if e.errno != 2: # 2: dir does not exist
|
||||
self.log.warning("Could not remove directory: %s (%s)",
|
||||
d, e)
|
||||
|
||||
for f in self.FILES_TO_BE_REMOVED:
|
||||
try:
|
||||
os.remove(f)
|
||||
except OSError as e:
|
||||
if e.errno != 2: # 2: file does not exist
|
||||
self.log.warning("Could not remove file: %s (%s)", f, e)
|
||||
|
||||
def file_restore(self, nologs=False):
|
||||
'''
|
||||
Restore all the files in the tarball.
|
||||
@@ -692,8 +511,6 @@ class Restore(admintool.AdminTool):
|
||||
cwd = os.getcwd()
|
||||
os.chdir('/')
|
||||
args = ['tar',
|
||||
'--xattrs',
|
||||
'--selinux',
|
||||
'-xzf',
|
||||
os.path.join(self.dir, 'files.tar')
|
||||
]
|
||||
@@ -701,9 +518,9 @@ class Restore(admintool.AdminTool):
|
||||
args.append('--exclude')
|
||||
args.append('var/log')
|
||||
|
||||
result = run(args, raiseonerr=False)
|
||||
if result.returncode != 0:
|
||||
self.log.critical('Restoring files failed: %s', result.error_log)
|
||||
(stdout, stderr, rc) = run(args, raiseonerr=False)
|
||||
if rc != 0:
|
||||
self.log.critical('Restoring files failed: %s', stderr)
|
||||
|
||||
os.chdir(cwd)
|
||||
|
||||
@@ -713,16 +530,16 @@ class Restore(admintool.AdminTool):
|
||||
Read the backup file header that contains the meta data about
|
||||
this particular backup.
|
||||
'''
|
||||
with open(self.header) as fd:
|
||||
config = SafeConfigParser()
|
||||
config.readfp(fd)
|
||||
fd = open(self.header)
|
||||
config = SafeConfigParser()
|
||||
config.readfp(fd)
|
||||
|
||||
self.backup_type = config.get('ipa', 'type')
|
||||
self.backup_time = config.get('ipa', 'time')
|
||||
self.backup_host = config.get('ipa', 'host')
|
||||
self.backup_ipa_version = config.get('ipa', 'ipa_version')
|
||||
self.backup_version = config.get('ipa', 'version')
|
||||
self.backup_services = config.get('ipa', 'services').split(',')
|
||||
self.backup_services = config.get('ipa', 'services')
|
||||
|
||||
|
||||
def extract_backup(self, keyring=None):
|
||||
@@ -752,15 +569,13 @@ class Restore(admintool.AdminTool):
|
||||
os.chdir(self.dir)
|
||||
|
||||
args = ['tar',
|
||||
'--xattrs',
|
||||
'--selinux',
|
||||
'-xzf',
|
||||
filename,
|
||||
'.'
|
||||
]
|
||||
run(args)
|
||||
|
||||
pent = pwd.getpwnam(constants.DS_USER)
|
||||
pent = pwd.getpwnam(DS_USER)
|
||||
os.chown(self.top_dir, pent.pw_uid, pent.pw_gid)
|
||||
recursive_chown(self.dir, pent.pw_uid, pent.pw_gid)
|
||||
|
||||
@@ -768,87 +583,56 @@ class Restore(admintool.AdminTool):
|
||||
# We can remove the decoded tarball
|
||||
os.unlink(filename)
|
||||
|
||||
|
||||
def __find_scripts_dir(self, instance):
|
||||
"""
|
||||
IPA stores its 389-ds scripts in a different directory than dogtag
|
||||
does so we need to probe for it.
|
||||
"""
|
||||
if instance != 'PKI-IPA':
|
||||
return os.path.join(paths.VAR_LIB_DIRSRV, 'scripts-%s' % instance)
|
||||
else:
|
||||
if sys.maxsize > 2**32L:
|
||||
libpath = 'lib64'
|
||||
else:
|
||||
libpath = 'lib'
|
||||
return os.path.join(paths.USR_DIR, libpath, 'dirsrv', 'slapd-PKI-IPA')
|
||||
|
||||
def __create_dogtag_log_dirs(self):
|
||||
"""
|
||||
If we are doing a full restore and the dogtag log directories do
|
||||
not exist then tomcat will fail to start.
|
||||
|
||||
The directory is different depending on whether we have a d9-based
|
||||
or a d10-based installation.
|
||||
or a d10-based installation. We can tell based on whether there is
|
||||
a PKI-IPA 389-ds instance.
|
||||
"""
|
||||
dirs = []
|
||||
# dogtag 10
|
||||
if (os.path.exists(paths.VAR_LIB_PKI_TOMCAT_DIR) and
|
||||
not os.path.exists(paths.TOMCAT_TOPLEVEL_DIR)):
|
||||
dirs += [paths.TOMCAT_TOPLEVEL_DIR,
|
||||
paths.TOMCAT_CA_DIR,
|
||||
paths.TOMCAT_CA_ARCHIVE_DIR,
|
||||
paths.TOMCAT_SIGNEDAUDIT_DIR]
|
||||
if os.path.exists(paths.ETC_SLAPD_PKI_IPA_DIR): # dogtag 9
|
||||
topdir = paths.PKI_CA_LOG_DIR
|
||||
dirs = [topdir,
|
||||
'/var/log/pki-ca/signedAudit,']
|
||||
else: # dogtag 10
|
||||
topdir = paths.TOMCAT_TOPLEVEL_DIR
|
||||
dirs = [topdir,
|
||||
paths.TOMCAT_CA_DIR,
|
||||
paths.TOMCAT_CA_ARCHIVE_DIR,
|
||||
paths.TOMCAT_SIGNEDAUDIT_DIR,]
|
||||
|
||||
if os.path.exists(topdir):
|
||||
return
|
||||
|
||||
try:
|
||||
pent = pwd.getpwnam(constants.PKI_USER)
|
||||
pent = pwd.getpwnam(PKI_USER)
|
||||
except KeyError:
|
||||
self.log.debug("No %s user exists, skipping CA directory creation",
|
||||
constants.PKI_USER)
|
||||
self.log.debug("No %s user exists, skipping CA directory creation" % PKI_USER)
|
||||
return
|
||||
self.log.debug('Creating log directories for dogtag')
|
||||
for dir in dirs:
|
||||
try:
|
||||
self.log.debug('Creating %s' % dir)
|
||||
os.mkdir(dir)
|
||||
os.chmod(dir, 0o770)
|
||||
os.mkdir(dir, 0770)
|
||||
os.chown(dir, pent.pw_uid, pent.pw_gid)
|
||||
tasks.restore_context(dir)
|
||||
except Exception as e:
|
||||
except Exception, e:
|
||||
# This isn't so fatal as to side-track the restore
|
||||
self.log.error('Problem with %s: %s' % (dir, e))
|
||||
|
||||
def restore_selinux_booleans(self):
|
||||
bools = dict(httpinstance.SELINUX_BOOLEAN_SETTINGS)
|
||||
if 'ADTRUST' in self.backup_services:
|
||||
if adtrustinstance:
|
||||
bools.update(adtrustinstance.SELINUX_BOOLEAN_SETTINGS)
|
||||
else:
|
||||
self.log.error(
|
||||
'The AD trust package was not found, '
|
||||
'not setting SELinux booleans.')
|
||||
try:
|
||||
tasks.set_selinux_booleans(bools)
|
||||
except ipapython.errors.SetseboolError as e:
|
||||
self.log.error('%s', e)
|
||||
|
||||
def cert_restore_prepare(self):
|
||||
cainstance.CAInstance().stop_tracking_certificates()
|
||||
httpinstance.HTTPInstance().stop_tracking_certificates()
|
||||
try:
|
||||
dsinstance.DsInstance().stop_tracking_certificates(
|
||||
installutils.realm_to_serverid(api.env.realm))
|
||||
except OSError:
|
||||
# When IPA is not installed, DS NSS DB does not exist
|
||||
pass
|
||||
|
||||
for basename in ('cert8.db', 'key3.db', 'secmod.db', 'pwdfile.txt'):
|
||||
filename = os.path.join(paths.IPA_NSSDB_DIR, basename)
|
||||
try:
|
||||
ipautil.backup_file(filename)
|
||||
except OSError as e:
|
||||
self.log.error("Failed to backup %s: %s" % (filename, e))
|
||||
|
||||
tasks.remove_ca_certs_from_systemwide_ca_store()
|
||||
|
||||
def cert_restore(self):
|
||||
try:
|
||||
certdb.update_ipa_nssdb()
|
||||
except RuntimeError as e:
|
||||
self.log.error("%s", e)
|
||||
|
||||
tasks.reload_systemwide_ca_store()
|
||||
|
||||
services.knownservices.certmonger.restart()
|
||||
|
||||
def init_api(self, **overrides):
|
||||
api.bootstrap(in_server=False, context='restore', **overrides)
|
||||
api.finalize()
|
||||
|
||||
self.instances = [installutils.realm_to_serverid(api.env.realm)]
|
||||
self.backends = ['userRoot', 'ipaca']
|
||||
|
||||
Reference in New Issue
Block a user