diff options
author | Aleksei Slaikovskii <aslaikov@redhat.com> | 2018-01-16 10:24:30 +0100 |
---|---|---|
committer | Christian Heimes <cheimes@redhat.com> | 2018-02-09 09:44:11 +0100 |
commit | 93b7c40158313b9f0f125706265ea0ac07fb4c0e (patch) | |
tree | 6596725a5cf34193a79035f0a5599243ebb2fa31 | |
parent | e6c707b168067ebb3705c21efc377acd29b23fff (diff) | |
download | freeipa-93b7c40158313b9f0f125706265ea0ac07fb4c0e.tar.gz freeipa-93b7c40158313b9f0f125706265ea0ac07fb4c0e.tar.xz freeipa-93b7c40158313b9f0f125706265ea0ac07fb4c0e.zip |
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
Reviewed-By: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
-rw-r--r-- | ipaserver/install/ipa_restore.py | 6 | ||||
-rw-r--r-- | ipatests/test_integration/test_backup_and_restore.py | 57 | ||||
-rw-r--r-- | ipatests/test_integration/test_simple_replication.py | 58 | ||||
-rw-r--r-- | 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 86b632728..bae71b090 100644 --- a/ipaserver/install/ipa_restore.py +++ b/ipaserver/install/ipa_restore.py @@ -423,6 +423,12 @@ class Restore(admintool.AdminTool): 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 13118fd77..7a2cee37f 100644 --- a/ipatests/test_integration/test_backup_and_restore.py +++ b/ipatests/test_integration/test_backup_and_restore.py @@ -29,8 +29,10 @@ from ipapython.dn import DN 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__) @@ -434,3 +436,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 fa21d75e6..6265f3fc5 100644 --- a/ipatests/test_integration/test_simple_replication.py +++ b/ipatests/test_integration/test_simple_replication.py @@ -22,8 +22,36 @@ from __future__ import print_function 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 1dc2a81e3..db4c12132 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 @@ class DummyClass(object): 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) |