summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksei Slaikovskii <aslaikov@redhat.com>2018-01-16 10:24:30 +0100
committerChristian Heimes <cheimes@redhat.com>2018-02-09 09:44:11 +0100
commit93b7c40158313b9f0f125706265ea0ac07fb4c0e (patch)
tree6596725a5cf34193a79035f0a5599243ebb2fa31
parente6c707b168067ebb3705c21efc377acd29b23fff (diff)
downloadfreeipa-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.py6
-rw-r--r--ipatests/test_integration/test_backup_and_restore.py57
-rw-r--r--ipatests/test_integration/test_simple_replication.py58
-rw-r--r--ipatests/util.py31
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)