Imported Upstream version 4.6.2

This commit is contained in:
Mario Fetka
2021-07-25 07:32:41 +02:00
commit 8ff3be4216
1788 changed files with 1900965 additions and 0 deletions

View File

@@ -0,0 +1,284 @@
# Authors:
# Petr Viktorin <pviktori@redhat.com>
#
# Copyright (C) 2011 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/>.
"""Pytest plugin for IPA Integration tests"""
from __future__ import print_function
import logging
import os
import tempfile
import shutil
import re
import pytest
from pytest_multihost import make_multihost_fixture
from ipapython import ipautil
from ipatests.test_util import yield_fixture
from .config import Config
from .env_config import get_global_config
from . import tasks
logger = logging.getLogger(__name__)
def pytest_addoption(parser):
group = parser.getgroup("IPA integration tests")
group.addoption(
'--logfile-dir', dest="logfile_dir", default=None,
help="Directory to store integration test logs in.")
def _get_logname_from_node(node):
name = node.nodeid
name = re.sub('\(\)/', '', name) # remove ()/
name = re.sub('[()]', '', name) # and standalone brackets
name = re.sub('(/|::)', '-', name)
return name
def collect_test_logs(node, logs_dict, test_config):
"""Collect logs from a test
Calls collect_logs
:param node: The pytest collection node (request.node)
:param logs_dict: Mapping of host to list of log filnames to collect
:param test_config: Pytest configuration
"""
collect_logs(
name=_get_logname_from_node(node),
logs_dict=logs_dict,
logfile_dir=test_config.getoption('logfile_dir'),
beakerlib_plugin=test_config.pluginmanager.getplugin('BeakerLibPlugin'),
)
def collect_systemd_journal(node, hosts, test_config):
"""Collect systemd journal from remote hosts
:param node: The pytest collection node (request.node)
:param hosts: List of hosts from which to collect journal
:param test_config: Pytest configuration
"""
name = _get_logname_from_node(node)
logfile_dir = test_config.getoption('logfile_dir')
if logfile_dir is None:
return
for host in hosts:
logger.info("Collecting journal from: %s", host.hostname)
topdirname = os.path.join(logfile_dir, name, host.hostname)
if not os.path.exists(topdirname):
os.makedirs(topdirname)
# Get journal content
cmd = host.run_command(
['journalctl', '--since', host.config.log_journal_since],
log_stdout=False, raiseonerr=False)
if cmd.returncode:
logger.error('An error occurred while collecting journal')
continue
# Write journal to file
with open(os.path.join(topdirname, "journal"), 'w') as f:
f.write(cmd.stdout_text)
def collect_logs(name, logs_dict, logfile_dir=None, beakerlib_plugin=None):
"""Collect logs from remote hosts
Calls collect_logs
:param name: Name under which logs arecollected, e.g. name of the test
:param logs_dict: Mapping of host to list of log filnames to collect
:param logfile_dir: Directory to log to
:param beakerlib_plugin:
BeakerLibProcess or BeakerLibPlugin used to collect tests for BeakerLib
If neither logfile_dir nor beakerlib_plugin is given, no tests are
collected.
"""
if logs_dict and (logfile_dir or beakerlib_plugin):
if logfile_dir:
remove_dir = False
else:
logfile_dir = tempfile.mkdtemp()
remove_dir = True
topdirname = os.path.join(logfile_dir, name)
for host, logs in logs_dict.items():
logger.info('Collecting logs from: %s', host.hostname)
dirname = os.path.join(topdirname, host.hostname)
if not os.path.isdir(dirname):
os.makedirs(dirname)
tarname = os.path.join(dirname, 'logs.tar.xz')
# get temporary file name
cmd = host.run_command(['mktemp'])
tmpname = cmd.stdout_text.strip()
# Tar up the logs on the remote server
cmd = host.run_command(
['tar', 'cJvf', tmpname, '--ignore-failed-read'] + logs,
log_stdout=False, raiseonerr=False)
if cmd.returncode:
logger.warning('Could not collect all requested logs')
# fetch tar file
with open(tarname, 'wb') as f:
f.write(host.get_file_contents(tmpname))
# delete from remote
host.run_command(['rm', '-f', tmpname])
# Unpack on the local side
ipautil.run(['tar', 'xJvf', 'logs.tar.xz'], cwd=dirname,
raiseonerr=False)
os.unlink(tarname)
if beakerlib_plugin:
# Use BeakerLib's rlFileSubmit on the indifidual files
# The resulting submitted filename will be
# $HOSTNAME-$FILENAME (with '/' replaced by '-')
beakerlib_plugin.run_beakerlib_command(['pushd', topdirname])
try:
for dirpath, _dirnames, filenames in os.walk(topdirname):
for filename in filenames:
fullname = os.path.relpath(
os.path.join(dirpath, filename), topdirname)
logger.debug('Submitting file: %s', fullname)
beakerlib_plugin.run_beakerlib_command(
['rlFileSubmit', fullname])
finally:
beakerlib_plugin.run_beakerlib_command(['popd'])
if remove_dir:
if beakerlib_plugin:
# The BeakerLib process runs asynchronously, let it clean up
# after it's done with the directory
beakerlib_plugin.run_beakerlib_command(
['rm', '-rvf', topdirname])
else:
shutil.rmtree(topdirname)
logs_dict.clear()
@pytest.fixture(scope='class')
def class_integration_logs():
"""Internal fixture providing class-level logs_dict"""
return {}
@yield_fixture
def integration_logs(class_integration_logs, request):
"""Provides access to test integration logs, and collects after each test
"""
yield class_integration_logs
hosts = class_integration_logs.keys()
collect_test_logs(request.node, class_integration_logs, request.config)
collect_systemd_journal(request.node, hosts, request.config)
@yield_fixture(scope='class')
def mh(request, class_integration_logs):
"""IPA's multihost fixture object
"""
cls = request.cls
domain_description = {
'type': 'IPA',
'hosts': {
'master': 1,
'replica': cls.num_replicas,
'client': cls.num_clients,
},
}
domain_description['hosts'].update(
{role: 1 for role in cls.required_extra_roles})
domain_descriptions = [domain_description]
for _i in range(cls.num_ad_domains):
domain_descriptions.append({
'type': 'AD',
'hosts': {'ad': 1, 'ad_subdomain': 1, 'ad_treedomain': 1},
})
mh = make_multihost_fixture(
request,
domain_descriptions,
config_class=Config,
_config=get_global_config(),
)
mh.domain = mh.config.domains[0]
[mh.master] = mh.domain.hosts_by_role('master')
mh.replicas = mh.domain.hosts_by_role('replica')
mh.clients = mh.domain.hosts_by_role('client')
cls.logs_to_collect = class_integration_logs
def collect_log(host, filename):
logger.info('Adding %s:%s to list of logs to collect',
host.external_hostname, filename)
class_integration_logs.setdefault(host, []).append(filename)
print(mh.config)
for host in mh.config.get_all_hosts():
host.add_log_collector(collect_log)
logger.info('Preparing host %s', host.hostname)
tasks.prepare_host(host)
setup_class(cls, mh)
mh._pytestmh_request.addfinalizer(lambda: teardown_class(cls))
yield mh.install()
for host in cls.get_all_hosts():
host.remove_log_collector(collect_log)
collect_test_logs(request.node, class_integration_logs, request.config)
def setup_class(cls, mh):
"""Add convenience attributes to the test class
This is deprecated in favor of the mh fixture.
To be removed when no more tests using this.
"""
cls.domain = mh.domain
cls.master = mh.master
cls.replicas = mh.replicas
cls.clients = mh.clients
cls.ad_domains = mh.config.ad_domains
def teardown_class(cls):
"""Remove convenience attributes from the test class
This is deprecated in favor of the mh fixture.
To be removed when no more tests using this.
"""
del cls.master
del cls.replicas
del cls.clients
del cls.ad_domains
del cls.domain

View File

@@ -0,0 +1,167 @@
# Authors:
# Petr Viktorin <pviktori@redhat.com>
# Tomas Babej <tbabej@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/>.
"""Utilities for configuration of multi-master tests"""
import logging
import random
import pytest_multihost.config
from ipapython.dn import DN
from ipalib.constants import MAX_DOMAIN_LEVEL
class Config(pytest_multihost.config.Config):
extra_init_args = {
'admin_name',
'admin_password',
'dirman_dn',
'dirman_password',
'nis_domain',
'ntp_server',
'ad_admin_name',
'ad_admin_password',
'dns_forwarder',
'domain_level',
'log_journal_since',
}
def __init__(self, **kwargs):
kwargs.setdefault('test_dir', '/root/ipatests')
super(Config, self).__init__(**kwargs)
admin_password = kwargs.get('admin_password') or 'Secret123'
self.admin_name = kwargs.get('admin_name') or 'admin'
self.admin_password = admin_password
self.dirman_dn = DN(kwargs.get('dirman_dn') or 'cn=Directory Manager')
self.dirman_password = kwargs.get('dirman_password') or admin_password
self.nis_domain = kwargs.get('nis_domain') or 'ipatest'
self.ntp_server = str(kwargs.get('ntp_server') or (
'%s.pool.ntp.org' % random.randint(0, 3)))
self.ad_admin_name = kwargs.get('ad_admin_name') or 'Administrator'
self.ad_admin_password = kwargs.get('ad_admin_password') or 'Secret123'
self.domain_level = kwargs.get('domain_level', MAX_DOMAIN_LEVEL)
# 8.8.8.8 is probably the best-known public DNS
self.dns_forwarder = kwargs.get('dns_forwarder') or '8.8.8.8'
self.debug = False
self.log_journal_since = kwargs.get('log_journal_since') or '-1h'
if self.domain_level is None:
self.domain_level = MAX_DOMAIN_LEVEL
def get_domain_class(self):
return Domain
def get_logger(self, name):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
return logger
@property
def ad_domains(self):
return [d for d in self.domains if d.type == 'AD']
def get_all_hosts(self):
for domain in self.domains:
for host in domain.hosts:
yield host
def to_dict(self):
extra_args = self.extra_init_args - {'dirman_dn'}
result = super(Config, self).to_dict(extra_args)
result['dirman_dn'] = str(self.dirman_dn)
return result
@classmethod
def from_env(cls, env):
from ipatests.pytest_plugins.integration.env_config import config_from_env
return config_from_env(env)
def to_env(self, **kwargs):
from ipatests.pytest_plugins.integration.env_config import config_to_env
return config_to_env(self, **kwargs)
class Domain(pytest_multihost.config.Domain):
"""Configuration for an IPA / AD domain"""
def __init__(self, config, name, domain_type):
self.type = str(domain_type)
self.config = config
self.name = str(name)
self.hosts = []
assert domain_type in ('IPA', 'AD')
self.realm = self.name.upper()
self.basedn = DN(*(('dc', p) for p in name.split('.')))
@property
def static_roles(self):
# Specific roles for each domain type are hardcoded
if self.type == 'IPA':
return ('master', 'replica', 'client', 'other')
elif self.type == 'AD':
return ('ad',)
else:
raise LookupError(self.type)
def get_host_class(self, host_dict):
from ipatests.pytest_plugins.integration.host import Host, WinHost
if self.type == 'IPA':
return Host
elif self.type == 'AD':
return WinHost
else:
raise LookupError(self.type)
@property
def master(self):
return self.host_by_role('master')
@property
def masters(self):
return self.hosts_by_role('master')
@property
def replicas(self):
return self.hosts_by_role('replica')
@property
def clients(self):
return self.hosts_by_role('client')
@property
def ads(self):
return self.hosts_by_role('ad')
@property
def other_hosts(self):
return self.hosts_by_role('other')
@classmethod
def from_env(cls, env, config, index, domain_type):
from ipatests.pytest_plugins.integration.env_config import domain_from_env
return domain_from_env(env, config, index, domain_type)
def to_env(self, **kwargs):
from ipatests.pytest_plugins.integration.env_config import domain_to_env
return domain_to_env(self, **kwargs)

View File

@@ -0,0 +1,366 @@
# Authors:
# Petr Viktorin <pviktori@redhat.com>
# Tomas Babej <tbabej@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/>.
"""Support for configuring multihost testing via environment variables
This is here to support tests configured for Beaker,
such as the ones at https://github.com/freeipa/tests/
"""
import os
import json
import collections
import six
from ipapython import ipautil
from ipatests.pytest_plugins.integration.config import Config, Domain
from ipalib.constants import MAX_DOMAIN_LEVEL
TESTHOST_PREFIX = 'TESTHOST_'
_SettingInfo = collections.namedtuple('Setting', 'name var_name default')
_setting_infos = (
# Directory on which test-specific files will be stored,
_SettingInfo('test_dir', 'IPATEST_DIR', '/root/ipatests'),
# File with root's private RSA key for SSH (default: ~/.ssh/id_rsa)
_SettingInfo('ssh_key_filename', 'IPA_ROOT_SSH_KEY', None),
# SSH password for root (used if root_ssh_key_filename is not set)
_SettingInfo('ssh_password', 'IPA_ROOT_SSH_PASSWORD', None),
_SettingInfo('admin_name', 'ADMINID', 'admin'),
_SettingInfo('admin_password', 'ADMINPW', 'Secret123'),
_SettingInfo('dirman_dn', 'ROOTDN', 'cn=Directory Manager'),
_SettingInfo('dirman_password', 'ROOTDNPWD', None),
# 8.8.8.8 is probably the best-known public DNS
_SettingInfo('dns_forwarder', 'DNSFORWARD', '8.8.8.8'),
_SettingInfo('nis_domain', 'NISDOMAIN', 'ipatest'),
_SettingInfo('ntp_server', 'NTPSERVER', None),
_SettingInfo('ad_admin_name', 'ADADMINID', 'Administrator'),
_SettingInfo('ad_admin_password', 'ADADMINPW', 'Secret123'),
_SettingInfo('ipv6', 'IPv6SETUP', False),
_SettingInfo('debug', 'IPADEBUG', False),
_SettingInfo('domain_level', 'DOMAINLVL', MAX_DOMAIN_LEVEL),
_SettingInfo('log_journal_since', 'LOG_JOURNAL_SINCE', '-1h'),
)
def get_global_config(env=None):
"""Create a test config from environment variables
If env is None, uses os.environ; otherwise env is an environment dict.
If IPATEST_YAML_CONFIG or IPATEST_JSON_CONFIG is set,
configuration is read from the named file.
For YAML, the PyYAML (python-yaml) library needs to be installed.
Otherwise, configuration is read from various curiously
named environment variables:
See _setting_infos for test-wide settings
MASTER_env1: FQDN of the master
REPLICA_env1: space-separated FQDNs of the replicas
CLIENT_env1: space-separated FQDNs of the clients
AD_env1: space-separated FQDNs of the Active Directories
OTHER_env1: space-separated FQDNs of other hosts
(same for _env2, _env3, etc)
BEAKERREPLICA1_IP_env1: IP address of replica 1 in env 1
(same for MASTER, CLIENT, or any extra defined ROLE)
For each machine that should be accessible to tests via extra roles,
the following environment variable is necessary:
TESTHOST_<role>_env1: FQDN of the machine with the extra role <role>
You can also optionally specify the IP address of the host:
BEAKER<role>_IP_env1: IP address of the machine of the extra role
The framework will try to resolve the hostname to its IP address
if not passed via this environment variable.
Also see env_normalize() for alternate variable names
"""
if env is None:
env = os.environ
env = dict(env)
return config_from_env(env)
def config_from_env(env):
if 'IPATEST_YAML_CONFIG' in env:
try:
import yaml
except ImportError as e:
raise ImportError(
"%s, please install PyYAML package to fix it" % e)
with open(env['IPATEST_YAML_CONFIG']) as file:
confdict = yaml.safe_load(file)
return Config.from_dict(confdict)
if 'IPATEST_JSON_CONFIG' in env:
with open(env['IPATEST_JSON_CONFIG']) as file:
confdict = json.load(file)
return Config.from_dict(confdict)
env_normalize(env)
kwargs = {s.name: env.get(s.var_name, s.default)
for s in _setting_infos}
kwargs['domains'] = []
# $IPv6SETUP needs to be 'TRUE' to enable ipv6
if isinstance(kwargs['ipv6'], six.string_types):
kwargs['ipv6'] = (kwargs['ipv6'].upper() == 'TRUE')
config = Config(**kwargs)
# Either IPA master or AD can define a domain
domain_index = 1
while (env.get('MASTER_env%s' % domain_index) or
env.get('AD_env%s' % domain_index)):
if env.get('MASTER_env%s' % domain_index):
# IPA domain takes precedence to AD domain in case of conflict
config.domains.append(domain_from_env(env, config, domain_index,
domain_type='IPA'))
else:
config.domains.append(domain_from_env(env, config, domain_index,
domain_type='AD'))
domain_index += 1
return config
def config_to_env(config, simple=True):
"""Convert this test config into environment variables"""
try:
env = collections.OrderedDict()
except AttributeError:
# Older Python versions
env = {}
for setting in _setting_infos:
value = getattr(config, setting.name)
if value in (None, False):
env[setting.var_name] = ''
elif value is True:
env[setting.var_name] = 'TRUE'
else:
env[setting.var_name] = str(value)
for domain in config.domains:
env_suffix = '_env%s' % (config.domains.index(domain) + 1)
env['DOMAIN%s' % env_suffix] = domain.name
env['RELM%s' % env_suffix] = domain.realm
env['BASEDN%s' % env_suffix] = str(domain.basedn)
for role in domain.roles:
hosts = domain.hosts_by_role(role)
prefix = ('' if role in domain.static_roles
else TESTHOST_PREFIX)
hostnames = ' '.join(h.hostname for h in hosts)
env['%s%s%s' % (prefix, role.upper(), env_suffix)] = hostnames
ext_hostnames = ' '.join(h.external_hostname for h in hosts)
env['BEAKER%s%s' % (role.upper(), env_suffix)] = ext_hostnames
ips = ' '.join(h.ip for h in hosts)
env['BEAKER%s_IP%s' % (role.upper(), env_suffix)] = ips
for i, host in enumerate(hosts, start=1):
suffix = '%s%s' % (role.upper(), i)
prefix = ('' if role in domain.static_roles
else TESTHOST_PREFIX)
ext_hostname = host.external_hostname
env['%s%s%s' % (prefix, suffix,
env_suffix)] = host.hostname
env['BEAKER%s%s' % (suffix, env_suffix)] = ext_hostname
env['BEAKER%s_IP%s' % (suffix, env_suffix)] = host.ip
if simple:
# Simple Vars for simplicity and backwards compatibility with older
# tests. This means no _env<NUM> suffix.
if config.domains:
default_domain = config.domains[0]
if default_domain.master:
env['MASTER'] = default_domain.master.hostname
env['BEAKERMASTER'] = default_domain.master.external_hostname
env['MASTERIP'] = default_domain.master.ip
if default_domain.replicas:
env['SLAVE'] = env['REPLICA'] = env['REPLICA_env1']
env['BEAKERSLAVE'] = env['BEAKERREPLICA_env1']
env['SLAVEIP'] = env['BEAKERREPLICA_IP_env1']
if default_domain.clients:
client = default_domain.clients[0]
env['CLIENT'] = client.hostname
env['BEAKERCLIENT'] = client.external_hostname
if len(default_domain.clients) >= 2:
client = default_domain.clients[1]
env['CLIENT2'] = client.hostname
env['BEAKERCLIENT2'] = client.external_hostname
return env
def env_normalize(env):
"""Fill env variables from alternate variable names
MASTER_env1 <- MASTER
REPLICA_env1 <- REPLICA, SLAVE
CLIENT_env1 <- CLIENT
similarly for BEAKER* variants: BEAKERMASTER1_env1 <- BEAKERMASTER, etc.
CLIENT_env1 gets extended with CLIENT2 or CLIENT2_env1
"""
def coalesce(name, *other_names):
"""If name is not set, set it to first existing env[other_name]"""
if name not in env:
for other_name in other_names:
try:
env[name] = env[other_name]
except KeyError:
pass
else:
return
else:
env[name] = ''
coalesce('MASTER_env1', 'MASTER')
coalesce('REPLICA_env1', 'REPLICA', 'SLAVE')
coalesce('CLIENT_env1', 'CLIENT')
coalesce('BEAKERMASTER1_env1', 'BEAKERMASTER')
coalesce('BEAKERREPLICA1_env1', 'BEAKERREPLICA', 'BEAKERSLAVE')
coalesce('BEAKERCLIENT1_env1', 'BEAKERCLIENT')
def extend(name, name2):
value = env.get(name2)
if value and value not in env[name].split(' '):
env[name] += ' ' + value
extend('CLIENT_env1', 'CLIENT2')
extend('CLIENT_env1', 'CLIENT2_env1')
def domain_from_env(env, config, index, domain_type):
# Roles available in the domain depend on the type of the domain
# Unix machines are added only to the IPA domains, Windows machines
# only to the AD domains
if domain_type == 'IPA':
master_role = 'MASTER'
else:
master_role = 'AD'
env_suffix = '_env%s' % index
master_env = '%s%s' % (master_role, env_suffix)
hostname, _dot, domain_name = env[master_env].partition('.')
domain = Domain(config, domain_name, domain_type)
for role in _roles_from_env(domain, env, env_suffix):
prefix = '' if role in domain.static_roles else TESTHOST_PREFIX
value = env.get('%s%s%s' % (prefix, role.upper(), env_suffix), '')
for host_index, hostname in enumerate(value.split(), start=1):
host = host_from_env(env, domain, hostname, role,
host_index, index)
domain.hosts.append(host)
if not domain.hosts:
raise ValueError('No hosts defined for %s' % env_suffix)
return domain
def _roles_from_env(domain, env, env_suffix):
for role in domain.static_roles:
yield role
# Extra roles are defined via env variables of form TESTHOST_key_envX
roles = set()
for var in sorted(env):
if var.startswith(TESTHOST_PREFIX) and var.endswith(env_suffix):
variable_split = var.split('_')
role_name = '_'.join(variable_split[1:-1])
if (role_name and not role_name[-1].isdigit()):
roles.add(role_name.lower())
for role in sorted(roles):
yield role
def domain_to_env(domain, **kwargs):
"""Return environment variables specific to this domain"""
env = domain.config.to_env(**kwargs)
env['DOMAIN'] = domain.name
env['RELM'] = domain.realm
env['BASEDN'] = str(domain.basedn)
return env
def host_from_env(env, domain, hostname, role, index, domain_index):
ip = env.get('BEAKER%s%s_IP_env%s' %
(role.upper(), index, domain_index), None)
external_hostname = env.get(
'BEAKER%s%s_env%s' % (role.upper(), index, domain_index), None)
cls = domain.get_host_class({})
return cls(domain, hostname, role, ip, external_hostname)
def host_to_env(host, **kwargs):
"""Return environment variables specific to this host"""
env = host.domain.to_env(**kwargs)
index = host.domain.hosts.index(host) + 1
domain_index = host.config.domains.index(host.domain) + 1
role = host.role.upper()
if host.role != 'master':
role += str(index)
env['MYHOSTNAME'] = host.hostname
env['MYBEAKERHOSTNAME'] = host.external_hostname
env['MYIP'] = host.ip
prefix = ('' if host.role in host.domain.static_roles
else TESTHOST_PREFIX)
env_suffix = '_env%s' % domain_index
env['MYROLE'] = '%s%s%s' % (prefix, role, env_suffix)
env['MYENV'] = str(domain_index)
return env
def env_to_script(env):
return ''.join(['export %s=%s\n' % (key, ipautil.shell_quote(value))
for key, value in env.items()])

View File

@@ -0,0 +1,70 @@
# 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/>.
"""Host class for integration testing"""
import pytest_multihost.host
from ipapython import ipaldap
class Host(pytest_multihost.host.Host):
"""Representation of a remote IPA host"""
@staticmethod
def _make_host(domain, hostname, role, ip, external_hostname):
# We need to determine the type of the host, this depends on the domain
# type, as we assume all Unix machines are in the Unix domain and
# all Windows machine in a AD domain
if domain.type == 'AD':
cls = WinHost
else:
cls = Host
return cls(domain, hostname, role, ip, external_hostname)
def ldap_connect(self):
"""Return an LDAPClient authenticated to this host as directory manager
"""
self.log.info('Connecting to LDAP at %s', self.external_hostname)
ldap_uri = ipaldap.get_ldap_uri(self.external_hostname)
ldap = ipaldap.LDAPClient(ldap_uri)
binddn = self.config.dirman_dn
self.log.info('LDAP bind as %s' % binddn)
ldap.simple_bind(binddn, self.config.dirman_password)
return ldap
@classmethod
def from_env(cls, env, domain, hostname, role, index, domain_index):
from ipatests.pytest_plugins.integration.env_config import host_from_env
return host_from_env(env, domain, hostname, role, index, domain_index)
def to_env(self, **kwargs):
from ipatests.pytest_plugins.integration.env_config import host_to_env
return host_to_env(self, **kwargs)
class WinHost(pytest_multihost.host.WinHost):
"""
Representation of a remote Windows host.
This serves as a sketch class once we move from manual preparation of
Active Directory to the automated setup.
"""

File diff suppressed because it is too large Load Diff