URL: https://github.com/freeipa/freeipa/pull/1560
Author: tiran
 Title: #1560: [Backport][ipa-4-6] Enable and start oddjobd after ipa-restore 
if it's not running. 
Action: opened

PR body:
"""
This PR was opened automatically because PR #1472 was pushed to master and 
backport to ipa-4-6 is required.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1560/head:pr1560
git checkout pr1560
From b86574165004951c8e9e10532409b40302658195 Mon Sep 17 00:00:00 2001
From: Aleksei Slaikovskii <aslai...@redhat.com>
Date: Tue, 16 Jan 2018 10:24:30 +0100
Subject: [PATCH] Enable and start oddjobd after ipa-restore if it's not
 running.

If after ipa-restore the service oddjobd is not running,
domain-level1 replica installation will fail during
ipa-replica-conncheck because this step is using oddjob
to start the process ipa-replica-conncheck on the master.

This patch fixes it. Also added regression test.

https://pagure.io/freeipa/issue/7234
---
 ipaserver/install/ipa_restore.py                   |  6 +++
 .../test_integration/test_backup_and_restore.py    | 57 +++++++++++++++++++++
 .../test_integration/test_simple_replication.py    | 58 ++++++++++++----------
 ipatests/util.py                                   | 31 ++++++++----
 4 files changed, 116 insertions(+), 36 deletions(-)

diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
index 99e6297b62..88c76ea706 100644
--- a/ipaserver/install/ipa_restore.py
+++ b/ipaserver/install/ipa_restore.py
@@ -423,6 +423,12 @@ def run(self):
                 logger.info('Restarting SSSD')
                 sssd = services.service('sssd', api)
                 sssd.restart()
+                logger.info('Restarting oddjobd')
+                oddjobd = services.service('oddjobd', api)
+                if not oddjobd.is_enabled():
+                    logger.info("Enabling oddjobd")
+                    oddjobd.enable()
+                oddjobd.start()
                 http.remove_httpd_ccaches()
                 # have the daemons pick up their restored configs
                 run([paths.SYSTEMCTL, "--system", "daemon-reload"])
diff --git a/ipatests/test_integration/test_backup_and_restore.py b/ipatests/test_integration/test_backup_and_restore.py
index 2e99376da0..ba24c366b4 100644
--- a/ipatests/test_integration/test_backup_and_restore.py
+++ b/ipatests/test_integration/test_backup_and_restore.py
@@ -28,8 +28,10 @@
 from ipatests.test_integration.base import IntegrationTest
 from ipatests.pytest_plugins.integration import tasks
 from ipatests.test_integration.test_dnssec import wait_until_record_is_signed
+from ipatests.test_integration.test_simple_replication import check_replication
 from ipatests.util import assert_deepequal
 
+
 logger = logging.getLogger(__name__)
 
 
@@ -421,3 +423,58 @@ class TestBackupReinstallRestoreWithKRA(BaseBackupAndRestoreWithKRA):
     def test_full_backup_reinstall_restore_with_vault(self):
         """backup, uninstall, reinstall, restore"""
         self._full_backup_restore_with_vault(reinstall=True)
+
+
+class TestBackupAndRestoreWithReplica(IntegrationTest):
+    """Regression test for https://pagure.io/freeipa/issue/7234""";
+    num_replicas = 1
+    topology = "star"
+
+    @classmethod
+    def install(cls, mh):
+        if cls.domain_level is None:
+            domain_level = cls.master.config.domain_level
+        else:
+            domain_level = cls.domain_level
+
+        if cls.topology is None:
+            return
+        else:
+            tasks.install_topo(
+                cls.topology, cls.master, [],
+                cls.clients, domain_level
+            )
+
+    def test_full_backup_and_restore_with_replica(self):
+        replica = self.replicas[0]
+
+        with restore_checker(self.master):
+            backup_path = backup(self.master)
+
+            logger.info("Backup path for %s is %s", self.master, backup_path)
+
+            self.master.run_command([
+                "ipa-server-install", "--uninstall", "-U"
+            ])
+
+            logger.info("Stopping and disabling oddjobd service")
+            self.master.run_command([
+                "systemctl", "stop", "oddjobd"
+            ])
+            self.master.run_command([
+                "systemctl", "disable", "oddjobd"
+            ])
+
+            dirman_password = self.master.config.dirman_password
+            self.master.run_command(
+                ["ipa-restore", backup_path],
+                stdin_text=dirman_password + '\nyes'
+            )
+
+            status = self.master.run_command([
+                "systemctl", "status", "oddjobd"
+            ])
+            assert "active (running)" in status.stdout_text
+
+        tasks.install_replica(self.master, replica)
+        check_replication(self.master, replica, "testuser1")
diff --git a/ipatests/test_integration/test_simple_replication.py b/ipatests/test_integration/test_simple_replication.py
index fa21d75e6b..6265f3fc5c 100644
--- a/ipatests/test_integration/test_simple_replication.py
+++ b/ipatests/test_integration/test_simple_replication.py
@@ -22,8 +22,36 @@
 import pytest
 
 from ipapython.dn import DN
-from ipatests.test_integration.base import IntegrationTest
 from ipatests.pytest_plugins.integration import tasks
+from ipatests.test_integration.base import IntegrationTest
+
+
+def check_replication(source_host, dest_host, login):
+    source_host.run_command([
+        "ipa", "user-add", login,
+        "--first", "test",
+        "--last", "user"
+    ])
+
+    source_ldap = source_host.ldap_connect()
+    tasks.wait_for_replication(source_ldap)
+
+    ldap = dest_host.ldap_connect()
+    tasks.wait_for_replication(ldap)
+
+    # Check using LDAP
+    basedn = dest_host.domain.basedn
+    user_dn = DN(
+        ("uid", login), ("cn", "users"),
+        ("cn", "accounts"), basedn
+    )
+    entry = ldap.get_entry(user_dn)
+    assert entry.dn == user_dn
+    assert entry["uid"] == [login]
+
+    # Check using CLI
+    result = dest_host.run_command(['ipa', 'user-show', login])
+    assert "User login: {}".format(login) in result.stdout_text
 
 
 @pytest.mark.ds_acceptance
@@ -36,37 +64,13 @@ class TestSimpleReplication(IntegrationTest):
     num_replicas = 1
     topology = 'star'
 
-    def check_replication(self, source_host, dest_host, login):
-        source_host.run_command(['ipa', 'user-add', login,
-                                 '--first', 'test',
-                                 '--last', 'user'])
-
-        source_ldap = source_host.ldap_connect()
-        tasks.wait_for_replication(source_ldap)
-
-        ldap = dest_host.ldap_connect()
-        tasks.wait_for_replication(ldap)
-
-        # Check using LDAP
-        basedn = dest_host.domain.basedn
-        user_dn = DN(('uid', login), ('cn', 'users'), ('cn', 'accounts'),
-                     basedn)
-        entry = ldap.get_entry(user_dn)
-        print(entry)
-        assert entry.dn == user_dn
-        assert entry['uid'] == [login]
-
-        # Check using CLI
-        result = dest_host.run_command(['ipa', 'user-show', login])
-        assert 'User login: %s' % login in result.stdout_text
-
     def test_user_replication_to_replica(self):
         """Test user replication master -> replica"""
-        self.check_replication(self.master, self.replicas[0], 'testuser1')
+        check_replication(self.master, self.replicas[0], 'testuser1')
 
     def test_user_replication_to_master(self):
         """Test user replication replica -> master"""
-        self.check_replication(self.replicas[0], self.master, 'testuser2')
+        check_replication(self.replicas[0], self.master, 'testuser2')
 
     def test_replica_removal(self):
         """Test replica removal"""
diff --git a/ipatests/util.py b/ipatests/util.py
index 1dc2a81e38..db4c121329 100644
--- a/ipatests/util.py
+++ b/ipatests/util.py
@@ -184,8 +184,8 @@ class Fuzzy(object):
     """
     Perform a fuzzy (non-strict) equality tests.
 
-    `Fuzzy` instances will likely be used when comparing nesting data-structures
-    using `assert_deepequal()`.
+    `Fuzzy` instances will likely be used when comparing nesting
+    data-structures using `assert_deepequal()`.
 
     By default a `Fuzzy` instance is equal to everything.  For example, all of
     these evaluate to ``True``:
@@ -363,7 +363,8 @@ def assert_deepequal(expected, got, doc='', stack=tuple()):
     >>> got = [u'Hello', dict(world=1.0)]
     >>> expected == got
     True
-    >>> assert_deepequal(expected, got, doc='Testing my nested data')  # doctest:+ELLIPSIS
+    >>> assert_deepequal(
+    ...    expected, got, doc='Testing my nested data')  # doctest: +ELLIPSIS
     Traceback (most recent call last):
       ...
     AssertionError: assert_deepequal: type(expected) is not type(got).
@@ -396,7 +397,11 @@ def assert_deepequal(expected, got, doc='', stack=tuple()):
     if isinstance(expected, DN):
         if isinstance(got, six.string_types):
             got = DN(got)
-    if not (isinstance(expected, Fuzzy) or callable(expected) or type(expected) is type(got)):
+    if (
+        not (isinstance(expected, Fuzzy)
+             or callable(expected)
+             or type(expected) is type(got))
+    ):
         raise AssertionError(
             TYPE % (doc, type(expected), type(got), expected, got, stack)
         )
@@ -686,22 +691,30 @@ def __init__(self, *calls):
     def __process(self, name_, args_, kw_):
         if self.__i >= len(self.__calls):
             raise AssertionError(
-                'extra call: %s, %r, %r' % (name_, args_, kw_)
+                "extra call: {name!s}, {args!r}, {kwargs!r}".format(
+                    name=name_, args=args_, kwargs=kw_
+                )
             )
         (name, args, kw, result) = self.__calls[self.__i]
         self.__i += 1
         i = self.__i
         if name_ != name:
             raise AssertionError(
-                'call %d should be to method %r; got %r' % (i, name, name_)
+                "call {0:d} should be to method {1!r}; got {2!r}".format(
+                    i, name, name_
+                )
             )
         if args_ != args:
             raise AssertionError(
-                'call %d to %r should have args %r; got %r' % (i, name, args, args_)
+                "call {0:d} to {1!r} should have args {2!r}; got {3!r}".format(
+                    i, name, args, args_
+                )
             )
         if kw_ != kw:
             raise AssertionError(
-                'call %d to %r should have kw %r, got %r' % (i, name, kw, kw_)
+                "call {0:d} to {1!r} should have kw {2!r}, got {3!r}".format(
+                    i, name, kw, kw_
+                )
             )
         if isinstance(result, Exception):
             raise result
@@ -799,7 +812,6 @@ def change_principal(principal, password=None, client=None, path=None,
     if client is None:
         client = api
 
-
     client.Backend.rpcclient.disconnect()
 
     try:
@@ -863,5 +875,6 @@ def host_keytab(hostname, options=None):
 def get_group_dn(cn):
     return DN(('cn', cn), api.env.container_group, api.env.basedn)
 
+
 def get_user_dn(uid):
     return DN(('uid', uid), api.env.container_user, api.env.basedn)
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to