blob: a1476e369f26a23b0157a77a542fbdeeffcd4870 [file] [log] [blame]
Dennis Dmitriev6f59add2016-10-18 13:45:27 +03001# Copyright 2016 Mirantis, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import pytest
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030016
17from tcp_tests.helpers import ext
Dennis Dmitriev535869c2016-11-16 22:38:06 +020018from tcp_tests.helpers import utils
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030019from tcp_tests import logger
20from tcp_tests import settings
21from tcp_tests.managers import envmanager_devops
22from tcp_tests.managers import envmanager_empty
23from tcp_tests.managers import underlay_ssh_manager
24
25LOG = logger.logger
26
27
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030028@pytest.fixture(scope="session")
29def hardware(request, config):
30 """Fixture for manage the hardware layer.
31
32 - start/stop/reboot libvirt/IPMI(/MaaS?) nodes
33 - snapshot/revert libvirt nodes (fuel-devops only)
34 - block/unblock libvirt networks/interfaces (fuel-devops only)
35
36 This fixture should get a hardware configuration from
37 'config' object or create a virtual/baremetal underlay
38 using EnvironmentManager.
39
40 Creates a snapshot 'hardware' with ready-to-use virtual environment
41 (Only for config.hardware.manager='devops'):
42 - just created virtual nodes in power-on state
43 - node volumes filled with necessary content
44 - node network interfaces connected to necessary devices
45
46 config.hardware.manager: one of ('devops', 'maas', None)
47 config.hardware.config: path to the config file for the manager
48 config.hardware.current_snapshot = Latest created or reverted snapshot
49
50 :rtype EnvironmentModel: if config.hardware.manager == 'devops'
51 :rtype EnvironmentManagerEmpty: if config.hardware.manager == 'empty'
52 """
53 env = None
54
55 manager = config.hardware.manager
56
57 if manager == 'empty':
58 # No environment manager is used.
59 # 'config' should contain config.underlay.ssh settings
60 # 'config' should contain config.underlay.current_snapshot setting
61 env = envmanager_empty.EnvironmentManagerEmpty(config=config)
62
63 elif manager == 'devops':
64 # fuel-devops environment manager is used.
65 # config.underlay.ssh settings can be empty or witn SSH to existing env
66 # config.underlay.current_snapshot
67 env = envmanager_devops.EnvironmentManager(config=config)
68 else:
69 raise Exception("Unknown hardware manager: '{}'".format(manager))
70
71 # for devops manager: power on nodes and wait for SSH
72 # for empty manager: do nothing
73 # for maas manager: provision nodes and wait for SSH
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030074 if not env.has_snapshot(ext.SNAPSHOT.hardware):
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030075 env.create_snapshot(ext.SNAPSHOT.hardware)
76
77 def fin():
78 if settings.SHUTDOWN_ENV_ON_TEARDOWN:
79 LOG.info("Shutdown environment...")
80 env.stop()
81
82 request.addfinalizer(fin)
83 return env
84
85
86@pytest.fixture(scope='function')
87def revert_snapshot(request, hardware):
88 """Revert snapshot for the test case
89
90 Usage:
91 @pytest.mark.revert_snapshot(name='<required_snapshot_name>')
92
93 If the mark 'revert_snapshot' is absend, or <required_snapshot_name>
94 not found, then an initial 'hardware' snapshot will be reverted.
95
96 :rtype string: name of the reverted snapshot or None
97 """
Dennis Dmitriev535869c2016-11-16 22:38:06 +020098 top_fixtures_snapshots = utils.get_top_fixtures_marks(
99 request, 'revert_snapshot')
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300100
Dennis Dmitriev535869c2016-11-16 22:38:06 +0200101 # Try to revert the best matches snapshot for the test
102 for snapshot_name in top_fixtures_snapshots:
103 if hardware.has_snapshot(snapshot_name) and \
104 hardware.has_snapshot_config(snapshot_name):
105 hardware.revert_snapshot(snapshot_name)
106 return snapshot_name
107
108 # Fallback to the basic snapshot
109 hardware.revert_snapshot(ext.SNAPSHOT.hardware)
110 return None
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300111
112
113@pytest.fixture(scope='function', autouse=True)
114def snapshot(request, hardware):
115 """Fixture for creating snapshot at the end of test if it's needed
116
117 Marks:
118 snapshot_needed(name=None) - make snapshot if test is passed. If
119 name argument provided, it will be used for creating snapshot,
120 otherwise, test function name will be used
121
122 fail_snapshot - make snapshot if test failed
123
124 :param request: pytest.python.FixtureRequest
125 :param env: envmanager.EnvironmentManager
126 """
127 snapshot_needed = request.keywords.get('snapshot_needed', None)
128 fail_snapshot = request.keywords.get('fail_snapshot', None)
129
130 def test_fin():
131 default_snapshot_name = getattr(request.node.function,
132 '_snapshot_name',
133 request.node.function.__name__)
134 if hasattr(request.node, 'rep_call') and request.node.rep_call.passed \
135 and snapshot_needed:
Dennis Dmitriev535869c2016-11-16 22:38:06 +0200136 snapshot_name = utils.extract_name_from_mark(snapshot_needed) or \
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300137 "{}_passed".format(default_snapshot_name)
Dennis Dmitriev411dd102017-09-15 16:04:47 +0300138 hardware.create_snapshot(snapshot_name, force=True)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300139
140 elif hasattr(request.node, 'rep_setup') and \
141 request.node.rep_setup.failed and fail_snapshot:
142 snapshot_name = "{0}_prep_failed".format(default_snapshot_name)
Dennis Dmitriev411dd102017-09-15 16:04:47 +0300143 hardware.create_snapshot(snapshot_name, force=True)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300144
145 elif hasattr(request.node, 'rep_call') and \
146 request.node.rep_call.failed and fail_snapshot:
147 snapshot_name = "{0}_failed".format(default_snapshot_name)
Dennis Dmitriev411dd102017-09-15 16:04:47 +0300148 hardware.create_snapshot(snapshot_name, force=True)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300149
150 request.addfinalizer(test_fin)
151
152
Dennis Dmitriev535869c2016-11-16 22:38:06 +0200153@pytest.mark.revert_snapshot(ext.SNAPSHOT.underlay)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300154@pytest.fixture(scope="function")
155def underlay(revert_snapshot, config, hardware):
156 """Fixture that should provide SSH access to underlay objects.
157
158 - Starts the 'hardware' environment and creates 'underlay' with required
159 configuration.
160 - Fills the following object using the 'hardware' fixture:
161 config.underlay.ssh = JSONList of SSH access credentials for nodes.
162 This list will be used for initialization the
163 model UnderlaySSHManager, see it for details.
164
165 :rtype UnderlaySSHManager: Object that encapsulate SSH credentials;
166 - provide list of underlay nodes;
167 - provide SSH access to underlay nodes using
168 node names or node IPs.
169 """
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300170 # Create Underlay
171 if not config.underlay.ssh:
172 # If config.underlay.ssh wasn't provided from external config, then
173 # try to get necessary data from hardware manager (fuel-devops)
Dennis Dmitriev7b9538f2017-05-15 17:01:34 +0300174
175 # for devops manager: power on nodes and wait for SSH
176 # for empty manager: do nothing
177 # for maas manager: provision nodes and wait for SSH
178 hardware.start(underlay_node_roles=config.underlay.roles,
179 timeout=config.underlay.bootstrap_timeout)
180
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300181 config.underlay.ssh = hardware.get_ssh_data(
182 roles=config.underlay.roles)
183
Dennis Dmitriev2a13a132016-11-04 00:56:23 +0200184 underlay = underlay_ssh_manager.UnderlaySSHManager(config)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300185
186 if not config.underlay.lvm:
187 underlay.enable_lvm(hardware.lvm_storages())
188 config.underlay.lvm = underlay.config_lvm
189
190 hardware.create_snapshot(ext.SNAPSHOT.underlay)
191
192 else:
193 # 1. hardware environment created and powered on
194 # 2. config.underlay.ssh contains SSH access to provisioned nodes
195 # (can be passed from external config with TESTS_CONFIGS variable)
Dennis Dmitriev2a13a132016-11-04 00:56:23 +0200196 underlay = underlay_ssh_manager.UnderlaySSHManager(config)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300197
198 return underlay
Tatyana Leontovichab47e162017-10-06 16:53:30 +0300199
200
201@pytest.fixture(scope='function', autouse=True)
202def grab_versions(request, underlay):
203 """Fixture for grab package versions at the end of test
204
205 Marks:
206 grab_versions(name=None) - make snapshot if test is passed. If
207 name argument provided, it will be used for creating data,
208 otherwise, test function name will be used
209
210 """
211 grab_version = request.keywords.get('grab_versions', None)
212
213 def test_fin():
214 default_name = getattr(request.node.function, '_name',
215 request.node.function.__name__)
216 if hasattr(request.node, 'rep_call') and request.node.rep_call.passed \
217 and grab_version:
218 artifact_name = utils.extract_name_from_mark(grab_version) or \
219 "{}".format(default_name)
220 underlay.get_logs(artifact_name)
221 request.addfinalizer(test_fin)