blob: d7351bf0ae3e9156af75b80b006e63ad86e5d102 [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
16from datetime import datetime
17
18from tcp_tests.helpers import ext
Dennis Dmitriev535869c2016-11-16 22:38:06 +020019from tcp_tests.helpers import utils
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030020from tcp_tests import logger
21from tcp_tests import settings
22from tcp_tests.managers import envmanager_devops
23from tcp_tests.managers import envmanager_empty
24from tcp_tests.managers import underlay_ssh_manager
25
26LOG = logger.logger
27
28
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030029@pytest.fixture(scope="session")
30def hardware(request, config):
31 """Fixture for manage the hardware layer.
32
33 - start/stop/reboot libvirt/IPMI(/MaaS?) nodes
34 - snapshot/revert libvirt nodes (fuel-devops only)
35 - block/unblock libvirt networks/interfaces (fuel-devops only)
36
37 This fixture should get a hardware configuration from
38 'config' object or create a virtual/baremetal underlay
39 using EnvironmentManager.
40
41 Creates a snapshot 'hardware' with ready-to-use virtual environment
42 (Only for config.hardware.manager='devops'):
43 - just created virtual nodes in power-on state
44 - node volumes filled with necessary content
45 - node network interfaces connected to necessary devices
46
47 config.hardware.manager: one of ('devops', 'maas', None)
48 config.hardware.config: path to the config file for the manager
49 config.hardware.current_snapshot = Latest created or reverted snapshot
50
51 :rtype EnvironmentModel: if config.hardware.manager == 'devops'
52 :rtype EnvironmentManagerEmpty: if config.hardware.manager == 'empty'
53 """
54 env = None
55
56 manager = config.hardware.manager
57
58 if manager == 'empty':
59 # No environment manager is used.
60 # 'config' should contain config.underlay.ssh settings
61 # 'config' should contain config.underlay.current_snapshot setting
62 env = envmanager_empty.EnvironmentManagerEmpty(config=config)
63
64 elif manager == 'devops':
65 # fuel-devops environment manager is used.
66 # config.underlay.ssh settings can be empty or witn SSH to existing env
67 # config.underlay.current_snapshot
68 env = envmanager_devops.EnvironmentManager(config=config)
69 else:
70 raise Exception("Unknown hardware manager: '{}'".format(manager))
71
72 # for devops manager: power on nodes and wait for SSH
73 # for empty manager: do nothing
74 # for maas manager: provision nodes and wait for SSH
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030075 if not env.has_snapshot(ext.SNAPSHOT.hardware):
Dennis Dmitriev75fce1b2016-10-18 15:04:28 +030076 env.start()
Dennis Dmitriev6f59add2016-10-18 13:45:27 +030077 env.create_snapshot(ext.SNAPSHOT.hardware)
78
79 def fin():
80 if settings.SHUTDOWN_ENV_ON_TEARDOWN:
81 LOG.info("Shutdown environment...")
82 env.stop()
83
84 request.addfinalizer(fin)
85 return env
86
87
88@pytest.fixture(scope='function')
89def revert_snapshot(request, hardware):
90 """Revert snapshot for the test case
91
92 Usage:
93 @pytest.mark.revert_snapshot(name='<required_snapshot_name>')
94
95 If the mark 'revert_snapshot' is absend, or <required_snapshot_name>
96 not found, then an initial 'hardware' snapshot will be reverted.
97
98 :rtype string: name of the reverted snapshot or None
99 """
Dennis Dmitriev535869c2016-11-16 22:38:06 +0200100 top_fixtures_snapshots = utils.get_top_fixtures_marks(
101 request, 'revert_snapshot')
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300102
Dennis Dmitriev535869c2016-11-16 22:38:06 +0200103 # Try to revert the best matches snapshot for the test
104 for snapshot_name in top_fixtures_snapshots:
105 if hardware.has_snapshot(snapshot_name) and \
106 hardware.has_snapshot_config(snapshot_name):
107 hardware.revert_snapshot(snapshot_name)
108 return snapshot_name
109
110 # Fallback to the basic snapshot
111 hardware.revert_snapshot(ext.SNAPSHOT.hardware)
112 return None
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300113
114
115@pytest.fixture(scope='function', autouse=True)
116def snapshot(request, hardware):
117 """Fixture for creating snapshot at the end of test if it's needed
118
119 Marks:
120 snapshot_needed(name=None) - make snapshot if test is passed. If
121 name argument provided, it will be used for creating snapshot,
122 otherwise, test function name will be used
123
124 fail_snapshot - make snapshot if test failed
125
126 :param request: pytest.python.FixtureRequest
127 :param env: envmanager.EnvironmentManager
128 """
129 snapshot_needed = request.keywords.get('snapshot_needed', None)
130 fail_snapshot = request.keywords.get('fail_snapshot', None)
131
132 def test_fin():
133 default_snapshot_name = getattr(request.node.function,
134 '_snapshot_name',
135 request.node.function.__name__)
136 if hasattr(request.node, 'rep_call') and request.node.rep_call.passed \
137 and snapshot_needed:
Dennis Dmitriev535869c2016-11-16 22:38:06 +0200138 snapshot_name = utils.extract_name_from_mark(snapshot_needed) or \
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300139 "{}_passed".format(default_snapshot_name)
140 hardware.create_snapshot(snapshot_name)
141
142 elif hasattr(request.node, 'rep_setup') and \
143 request.node.rep_setup.failed and fail_snapshot:
144 snapshot_name = "{0}_prep_failed".format(default_snapshot_name)
145 hardware.create_snapshot(snapshot_name)
146
147 elif hasattr(request.node, 'rep_call') and \
148 request.node.rep_call.failed and fail_snapshot:
149 snapshot_name = "{0}_failed".format(default_snapshot_name)
150 hardware.create_snapshot(snapshot_name)
151
152 request.addfinalizer(test_fin)
153
154
Dennis Dmitriev535869c2016-11-16 22:38:06 +0200155@pytest.mark.revert_snapshot(ext.SNAPSHOT.underlay)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300156@pytest.fixture(scope="function")
157def underlay(revert_snapshot, config, hardware):
158 """Fixture that should provide SSH access to underlay objects.
159
160 - Starts the 'hardware' environment and creates 'underlay' with required
161 configuration.
162 - Fills the following object using the 'hardware' fixture:
163 config.underlay.ssh = JSONList of SSH access credentials for nodes.
164 This list will be used for initialization the
165 model UnderlaySSHManager, see it for details.
166
167 :rtype UnderlaySSHManager: Object that encapsulate SSH credentials;
168 - provide list of underlay nodes;
169 - provide SSH access to underlay nodes using
170 node names or node IPs.
171 """
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300172 # Create Underlay
173 if not config.underlay.ssh:
174 # If config.underlay.ssh wasn't provided from external config, then
175 # try to get necessary data from hardware manager (fuel-devops)
176 config.underlay.ssh = hardware.get_ssh_data(
177 roles=config.underlay.roles)
178
Dennis Dmitriev2a13a132016-11-04 00:56:23 +0200179 underlay = underlay_ssh_manager.UnderlaySSHManager(config)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300180
181 if not config.underlay.lvm:
182 underlay.enable_lvm(hardware.lvm_storages())
183 config.underlay.lvm = underlay.config_lvm
184
185 hardware.create_snapshot(ext.SNAPSHOT.underlay)
186
187 else:
188 # 1. hardware environment created and powered on
189 # 2. config.underlay.ssh contains SSH access to provisioned nodes
190 # (can be passed from external config with TESTS_CONFIGS variable)
Dennis Dmitriev2a13a132016-11-04 00:56:23 +0200191 underlay = underlay_ssh_manager.UnderlaySSHManager(config)
Dennis Dmitriev6f59add2016-10-18 13:45:27 +0300192
193 return underlay