mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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>
This commit is contained in:
parent
e6c707b168
commit
93b7c40158
@ -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"])
|
||||
|
@ -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")
|
||||
|
@ -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"""
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user