0201d8
From 0dfae3e9f16d91116a6769e25bbbee0ef1e485d2 Mon Sep 17 00:00:00 2001
0201d8
From: David Kupka <dkupka@redhat.com>
0201d8
Date: Wed, 4 Mar 2015 10:06:47 -0500
0201d8
Subject: [PATCH] Restore default.conf and use it to build API.
0201d8
0201d8
When restoring ipa after uninstallation we need to extract and load
0201d8
configuration of the restored environment.
0201d8
0201d8
https://fedorahosted.org/freeipa/ticket/4896
0201d8
0201d8
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
0201d8
---
0201d8
 ipaserver/install/ipa_restore.py | 64 ++++++++++++++++++++++++++++++----------
0201d8
 1 file changed, 48 insertions(+), 16 deletions(-)
0201d8
0201d8
diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
0201d8
index efe3b9b1c0c10775b3a72b9d843924263526209a..a5ecd5f62bc85918fe697d98109bd3a82120f355 100644
0201d8
--- a/ipaserver/install/ipa_restore.py
0201d8
+++ b/ipaserver/install/ipa_restore.py
0201d8
@@ -27,7 +27,7 @@ from ConfigParser import SafeConfigParser
0201d8
 import ldif
0201d8
 import itertools
0201d8
 
0201d8
-from ipalib import api, errors
0201d8
+from ipalib import api, errors, constants
0201d8
 from ipapython import version, ipautil, certdb, dogtag
0201d8
 from ipapython.ipautil import run, user_input
0201d8
 from ipapython import admintool
0201d8
@@ -203,15 +203,12 @@ class Restore(admintool.AdminTool):
0201d8
         options = self.options
0201d8
         super(Restore, self).run()
0201d8
 
0201d8
-        api.bootstrap(in_server=False, context='restore')
0201d8
-        api.finalize()
0201d8
-
0201d8
         self.backup_dir = self.args[0]
0201d8
         if not os.path.isabs(self.backup_dir):
0201d8
             self.backup_dir = os.path.join(BACKUP_DIR, self.backup_dir)
0201d8
 
0201d8
         self.log.info("Preparing restore from %s on %s",
0201d8
-                      self.backup_dir, api.env.host)
0201d8
+                      self.backup_dir, constants.FQDN)
0201d8
 
0201d8
         self.header = os.path.join(self.backup_dir, 'header')
0201d8
 
0201d8
@@ -225,9 +222,6 @@ class Restore(admintool.AdminTool):
0201d8
         else:
0201d8
             restore_type = self.backup_type
0201d8
 
0201d8
-        instances = [realm_to_serverid(api.env.realm), 'PKI-IPA']
0201d8
-        backends = ['userRoot', 'ipaca']
0201d8
-
0201d8
         # These checks would normally be in the validate method but
0201d8
         # we need to know the type of backup we're dealing with.
0201d8
         if restore_type == 'FULL':
0201d8
@@ -241,6 +235,8 @@ class Restore(admintool.AdminTool):
0201d8
         else:
0201d8
             installutils.check_server_configuration()
0201d8
 
0201d8
+            self.init_api()
0201d8
+
0201d8
             if options.instance:
0201d8
                 instance_dir = (paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE %
0201d8
                                 options.instance)
0201d8
@@ -248,10 +244,10 @@ class Restore(admintool.AdminTool):
0201d8
                     raise admintool.ScriptError(
0201d8
                         "Instance %s does not exist" % options.instance)
0201d8
 
0201d8
-                instances = [options.instance]
0201d8
+                self.instances = [options.instance]
0201d8
 
0201d8
             if options.backend:
0201d8
-                for instance in instances:
0201d8
+                for instance in self.instances:
0201d8
                     db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
0201d8
                               (instance, options.backend))
0201d8
                     if os.path.exists(db_dir):
0201d8
@@ -260,9 +256,10 @@ class Restore(admintool.AdminTool):
0201d8
                     raise admintool.ScriptError(
0201d8
                         "Backend %s does not exist" % options.backend)
0201d8
 
0201d8
-                backends = [options.backend]
0201d8
+                self.backends = [options.backend]
0201d8
 
0201d8
-            for instance, backend in itertools.product(instances, backends):
0201d8
+            for instance, backend in itertools.product(self.instances,
0201d8
+                                                       self.backends):
0201d8
                 db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
0201d8
                           (instance, backend))
0201d8
                 if os.path.exists(db_dir):
0201d8
@@ -274,10 +271,10 @@ class Restore(admintool.AdminTool):
0201d8
         self.log.info("Performing %s restore from %s backup" %
0201d8
                       (restore_type, self.backup_type))
0201d8
 
0201d8
-        if self.backup_host != api.env.host:
0201d8
+        if self.backup_host != constants.FQDN:
0201d8
             raise admintool.ScriptError(
0201d8
                 "Host name %s does not match backup name %s" %
0201d8
-                (api.env.host, self.backup_host))
0201d8
+                (constants.FQDN, self.backup_host))
0201d8
 
0201d8
         if self.backup_ipa_version != str(version.VERSION):
0201d8
             self.log.warning(
0201d8
@@ -307,9 +304,13 @@ class Restore(admintool.AdminTool):
0201d8
 
0201d8
             self.extract_backup(options.gpg_keyring)
0201d8
 
0201d8
+            if restore_type == 'FULL':
0201d8
+                self.restore_default_conf()
0201d8
+                self.init_api(confdir=self.dir + paths.ETC_IPA)
0201d8
+
0201d8
             databases = []
0201d8
-            for instance in instances:
0201d8
-                for backend in backends:
0201d8
+            for instance in self.instances:
0201d8
+                for backend in self.backends:
0201d8
                     database = (instance, backend)
0201d8
                     ldiffile = os.path.join(self.dir, '%s-%s.ldif' % database)
0201d8
                     if os.path.exists(ldiffile):
0201d8
@@ -607,6 +608,30 @@ class Restore(admintool.AdminTool):
0201d8
                 self.log.critical("bak2db failed: %s" % stderr)
0201d8
 
0201d8
 
0201d8
+    def restore_default_conf(self):
0201d8
+        '''
0201d8
+        Restore paths.IPA_DEFAULT_CONF to temporary directory.
0201d8
+
0201d8
+        Primary purpose of this method is to get cofiguration for api
0201d8
+        finalization when restoring ipa after uninstall.
0201d8
+        '''
0201d8
+        cwd = os.getcwd()
0201d8
+        os.chdir(self.dir)
0201d8
+        args = ['tar',
0201d8
+                '--xattrs',
0201d8
+                '--selinux',
0201d8
+                '-xzf',
0201d8
+                os.path.join(self.dir, 'files.tar'),
0201d8
+                paths.IPA_DEFAULT_CONF[1:],
0201d8
+               ]
0201d8
+
0201d8
+        (stdout, stderr, rc) = run(args, raiseonerr=False)
0201d8
+        if rc != 0:
0201d8
+            self.log.critical('Restoring %s failed: %s' %
0201d8
+                              (paths.IPA_DEFAULT_CONF, stderr))
0201d8
+        os.chdir(cwd)
0201d8
+
0201d8
+
0201d8
     def file_restore(self, nologs=False):
0201d8
         '''
0201d8
         Restore all the files in the tarball.
0201d8
@@ -803,3 +828,10 @@ class Restore(admintool.AdminTool):
0201d8
         tasks.reload_systemwide_ca_store()
0201d8
 
0201d8
         services.knownservices.certmonger.restart()
0201d8
+
0201d8
+    def init_api(self, **overrides):
0201d8
+        api.bootstrap(in_server=False, context='restore', **overrides)
0201d8
+        api.finalize()
0201d8
+
0201d8
+        self.instances = [realm_to_serverid(api.env.realm), 'PKI-IPA']
0201d8
+        self.backends = ['userRoot', 'ipaca']
0201d8
-- 
0201d8
2.1.0
0201d8