mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add install_topo to test tasks
This allows a cluster of replicas and clients to be installed in a named topology. Several named topologies are available (star, line, complete, tree, tree2) and new ones can be defined as a simple function.
This commit is contained in:
parent
ac70c2cc5c
commit
13f4b7e9cf
@ -35,7 +35,7 @@ log = log_mgr.get_logger(__name__)
|
||||
class IntegrationTest(object):
|
||||
num_replicas = 0
|
||||
num_clients = 0
|
||||
topology = 'none'
|
||||
topology = None
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
@ -78,14 +78,11 @@ class IntegrationTest(object):
|
||||
|
||||
@classmethod
|
||||
def install(cls):
|
||||
if cls.topology == 'none':
|
||||
if cls.topology is None:
|
||||
return
|
||||
elif cls.topology == 'star':
|
||||
tasks.install_master(cls.master)
|
||||
for replica in cls.replicas:
|
||||
tasks.install_replica(cls.master, replica)
|
||||
else:
|
||||
raise ValueError('Unknown topology %s' % cls.topology)
|
||||
tasks.install_topo(cls.topology,
|
||||
cls.master, cls.replicas, cls.clients)
|
||||
|
||||
@classmethod
|
||||
def teardown_class(cls):
|
||||
|
@ -162,6 +162,10 @@ class Host(object):
|
||||
|
||||
self.log_collectors = []
|
||||
|
||||
def __str__(self):
|
||||
template = ('<{s.__class__.__name__} {s.hostname} ({s.role})>')
|
||||
return template.format(s=self)
|
||||
|
||||
def __repr__(self):
|
||||
template = ('<{s.__module__}.{s.__class__.__name__} '
|
||||
'{s.hostname} ({s.role})>')
|
||||
@ -222,9 +226,11 @@ class Host(object):
|
||||
:param raiseonerr: If true, an exception will be raised if the command
|
||||
does not exit with return code 0
|
||||
"""
|
||||
assert self.transport
|
||||
|
||||
self._command_index += 1
|
||||
command = RemoteCommand(self, argv, index=self._command_index,
|
||||
log_stdout=log_stdout)
|
||||
self._command_index += 1
|
||||
|
||||
if cwd is None:
|
||||
cwd = self.config.test_dir
|
||||
|
@ -22,6 +22,8 @@
|
||||
import os
|
||||
import textwrap
|
||||
import re
|
||||
import collections
|
||||
import itertools
|
||||
|
||||
from ipapython import ipautil
|
||||
from ipapython.ipa_log_manager import log_mgr
|
||||
@ -234,3 +236,146 @@ def uninstall_client(host):
|
||||
host.run_command(['ipa-client-install', '--uninstall', '-U'],
|
||||
raiseonerr=False)
|
||||
unapply_fixes(host)
|
||||
|
||||
|
||||
def get_topo(name_or_func):
|
||||
"""Get a topology function by name
|
||||
|
||||
A topology function receives a master and list of replicas, and yields
|
||||
(parent, child) pairs, where "child" should be installed from "parent"
|
||||
(or just connected if already installed)
|
||||
|
||||
If a callable is given instead of name, it is returned directly
|
||||
"""
|
||||
if callable(name_or_func):
|
||||
return name_or_func
|
||||
return topologies[name_or_func]
|
||||
|
||||
|
||||
def _topo(name):
|
||||
"""Decorator that registers a function in topologies under a given name"""
|
||||
def add_topo(func):
|
||||
topologies[name] = func
|
||||
return func
|
||||
return add_topo
|
||||
topologies = collections.OrderedDict()
|
||||
|
||||
|
||||
@_topo('star')
|
||||
def star_topo(master, replicas):
|
||||
r"""All replicas are connected to the master
|
||||
|
||||
Rn R1 R2
|
||||
\ | /
|
||||
R7-- M -- R3
|
||||
/ | \
|
||||
R6 R5 R4
|
||||
"""
|
||||
for replica in replicas:
|
||||
yield master, replica
|
||||
|
||||
|
||||
@_topo('line')
|
||||
def line_topo(master, replicas):
|
||||
r"""Line topology
|
||||
|
||||
M
|
||||
\
|
||||
R1
|
||||
\
|
||||
R2
|
||||
\
|
||||
R3
|
||||
\
|
||||
...
|
||||
"""
|
||||
for replica in replicas:
|
||||
yield master, replica
|
||||
master = replica
|
||||
|
||||
|
||||
@_topo('complete')
|
||||
def complete_topo(master, replicas):
|
||||
r"""Each host connected to each other host
|
||||
|
||||
M--R1
|
||||
|\/|
|
||||
|/\|
|
||||
R2-R3
|
||||
"""
|
||||
for replica in replicas:
|
||||
yield master, replica
|
||||
for replica1, replica2 in itertools.combinations(replicas, 2):
|
||||
yield replica1, replica2
|
||||
|
||||
|
||||
@_topo('tree')
|
||||
def tree_topo(master, replicas):
|
||||
r"""Binary tree topology
|
||||
|
||||
M
|
||||
/ \
|
||||
/ \
|
||||
R1 R2
|
||||
/ \ / \
|
||||
R3 R4 R5 R6
|
||||
/
|
||||
R7 ...
|
||||
|
||||
"""
|
||||
replicas = list(replicas)
|
||||
|
||||
def _masters():
|
||||
for host in [master] + replicas:
|
||||
yield host
|
||||
yield host
|
||||
|
||||
for parent, child in zip(_masters(), replicas):
|
||||
yield parent, child
|
||||
|
||||
|
||||
@_topo('tree2')
|
||||
def tree2_topo(master, replicas):
|
||||
r"""First replica connected directly to master, the rest in a line
|
||||
|
||||
M
|
||||
/ \
|
||||
R1 R2
|
||||
\
|
||||
R3
|
||||
\
|
||||
R4
|
||||
\
|
||||
...
|
||||
|
||||
"""
|
||||
if replicas:
|
||||
yield master, replicas[0]
|
||||
for replica in replicas[1:]:
|
||||
yield master, replica
|
||||
master = replica
|
||||
|
||||
|
||||
def install_topo(topo, master, replicas, clients,
|
||||
skip_master=False, setup_replica_cas=True):
|
||||
"""Install IPA servers and clients in the given topology"""
|
||||
replicas = list(replicas)
|
||||
installed = {master}
|
||||
if not skip_master:
|
||||
install_master(master)
|
||||
for parent, child in get_topo(topo)(master, replicas):
|
||||
if child in installed:
|
||||
log.info('Connecting replica %s to %s' % (parent, child))
|
||||
connect_replica(parent, child)
|
||||
else:
|
||||
log.info('Installing replica %s from %s' % (parent, child))
|
||||
install_replica(parent, child, setup_ca=setup_replica_cas)
|
||||
installed.add(child)
|
||||
install_clients([master] + replicas, clients)
|
||||
|
||||
|
||||
def install_clients(servers, clients):
|
||||
"""Install IPA clients, distributing them among the given servers"""
|
||||
for server, client in itertools.izip(itertools.cycle(servers), clients):
|
||||
log.info('Installing client %s on %s' % (server, client))
|
||||
install_client(server, client)
|
||||
|
98
ipatests/test_integration/test_topologies.py
Normal file
98
ipatests/test_integration/test_topologies.py
Normal file
@ -0,0 +1,98 @@
|
||||
# Authors:
|
||||
# Petr Viktorin <pviktori@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2013 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from ipatests.test_integration import tasks
|
||||
|
||||
|
||||
def test_topology_star():
|
||||
topo = tasks.get_topo('star')
|
||||
assert topo == tasks.star_topo
|
||||
assert list(topo('M', [1, 2, 3, 4, 5])) == [
|
||||
('M', 1),
|
||||
('M', 2),
|
||||
('M', 3),
|
||||
('M', 4),
|
||||
('M', 5),
|
||||
]
|
||||
assert list(topo('M', [])) == []
|
||||
|
||||
|
||||
def test_topology_line():
|
||||
topo = tasks.get_topo('line')
|
||||
assert topo == tasks.line_topo
|
||||
assert list(topo('M', [1, 2, 3, 4, 5])) == [
|
||||
('M', 1),
|
||||
(1, 2),
|
||||
(2, 3),
|
||||
(3, 4),
|
||||
(4, 5),
|
||||
]
|
||||
assert list(topo('M', [])) == []
|
||||
|
||||
|
||||
def test_topology_tree():
|
||||
topo = tasks.get_topo('tree')
|
||||
assert topo == tasks.tree_topo
|
||||
assert list(topo('M', [1, 2, 3, 4, 5])) == [
|
||||
('M', 1),
|
||||
('M', 2),
|
||||
(1, 3),
|
||||
(1, 4),
|
||||
(2, 5),
|
||||
]
|
||||
assert list(topo('M', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) == [
|
||||
('M', 1),
|
||||
('M', 2),
|
||||
(1, 3),
|
||||
(1, 4),
|
||||
(2, 5),
|
||||
(2, 6),
|
||||
(3, 7),
|
||||
(3, 8),
|
||||
(4, 9),
|
||||
(4, 10),
|
||||
]
|
||||
assert list(topo('M', [])) == []
|
||||
|
||||
|
||||
def test_topology_tree2():
|
||||
topo = tasks.get_topo('tree2')
|
||||
assert topo == tasks.tree2_topo
|
||||
assert list(topo('M', [1, 2, 3, 4, 5])) == [
|
||||
('M', 1),
|
||||
('M', 2),
|
||||
(2, 3),
|
||||
(3, 4),
|
||||
(4, 5),
|
||||
]
|
||||
assert list(topo('M', [])) == []
|
||||
|
||||
|
||||
def test_topology_complete():
|
||||
topo = tasks.get_topo('complete')
|
||||
assert topo == tasks.complete_topo
|
||||
assert list(topo('M', [1, 2, 3])) == [
|
||||
('M', 1),
|
||||
('M', 2),
|
||||
('M', 3),
|
||||
(1, 2),
|
||||
(1, 3),
|
||||
(2, 3),
|
||||
]
|
||||
assert list(topo('M', [])) == []
|
Loading…
Reference in New Issue
Block a user