fuel-ccp-tests/fuel_ccp_tests/fixtures/underlay_fixtures.py

203 lines
7.5 KiB
Python

# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import pytest
from fuel_ccp_tests.helpers import ext
from fuel_ccp_tests import logger
from fuel_ccp_tests import settings
from fuel_ccp_tests.managers import envmanager_devops
from fuel_ccp_tests.managers import envmanager_empty
from fuel_ccp_tests.managers import underlay_ssh_manager
LOG = logger.logger
def extract_name_from_mark(mark):
"""Simple function to extract name from mark
:param mark: pytest.mark.MarkInfo
:rtype: string or None
"""
if mark:
if len(mark.args) > 0:
return mark.args[0]
elif 'name' in mark.kwargs:
return mark.kwargs['name']
return None
@pytest.fixture(scope="session")
def hardware(request, config):
"""Fixture for manage the hardware layer.
- start/stop/reboot libvirt/IPMI(/MaaS?) nodes
- snapshot/revert libvirt nodes (fuel-devops only)
- block/unblock libvirt networks/interfaces (fuel-devops only)
This fixture should get a hardware configuration from
'config' object or create a virtual/baremetal underlay
using EnvironmentManager.
Input data:
config.hardware.manager: one of ('devops', 'maas', None)
config.hardware.config: path to the config file for the manager
...
(additional variables for the hardware manager)
Output data:
config.status_name = Latest created or reverted snapshot name
config.underlay.ssh = JSONList of SSH access credentials for nodes.
This list will be used for initialization the
model UnderlaySSHManager, see it for details.
:rtype EnvironmentModel: if config.hardware.manager == 'devops'
:rtype NoneType: if config.hardware.manager == None
"""
env = None
manager = config.hardware.manager
if manager == 'empty':
# No environment manager is used.
# 'config' should contain config.underlay.ssh settings
# 'config' should contain config.underlay.current_snapshot setting
env = envmanager_empty.EnvironmentManagerEmpty(config=config)
elif manager == 'devops':
# fuel-devops environment manager is used.
# config.underlay.ssh settings can be empty or witn SSH to existing env
# config.underlay.current_snapshot
env = envmanager_devops.EnvironmentManager(config=config)
else:
raise Exception("Unknown hardware manager: '{}'".format(manager))
def fin():
if settings.SHUTDOWN_ENV_ON_TEARDOWN:
LOG.info("Shutdown environment...")
env.stop()
request.addfinalizer(fin)
return env
@pytest.fixture(scope='function')
def revert_snapshot(request, hardware):
"""Extract snapshot name from mark
Marks:
revert_snapshot - if used this mark with 'name' parameter,
use given name as result
:rtype string: name of the reverted snapshot or None
"""
revert_snapshot = request.keywords.get('revert_snapshot', None)
snapshot_name = extract_name_from_mark(revert_snapshot)
if snapshot_name and \
hardware.has_snapshot(snapshot_name) and \
hardware.has_snapshot_config(snapshot_name):
hardware.revert_snapshot(snapshot_name)
return snapshot_name
@pytest.fixture(scope='function', autouse=True)
def snapshot(request, hardware):
"""Fixture for creating snapshot at the end of test if it's needed
Marks:
snapshot_needed(name=None) - make snapshot if test is passed. If
name argument provided, it will be used for creating snapshot,
otherwise, test function name will be used
fail_snapshot - make snapshot if test failed
:param request: pytest.python.FixtureRequest
:param env: envmanager.EnvironmentManager
"""
snapshot_needed = request.keywords.get('snapshot_needed', None)
fail_snapshot = request.keywords.get('fail_snapshot', None)
def test_fin():
default_snapshot_name = getattr(request.node.function,
'_snapshot_name',
request.node.function.__name__)
if hasattr(request.node, 'rep_call') and request.node.rep_call.passed \
and snapshot_needed:
snapshot_name = extract_name_from_mark(snapshot_needed) or \
"{}_passed".format(default_snapshot_name)
hardware.create_snapshot(snapshot_name)
elif hasattr(request.node, 'rep_setup') and \
request.node.rep_setup.failed and fail_snapshot:
snapshot_name = "{0}_prep_failed".format(default_snapshot_name)
hardware.create_snapshot(snapshot_name)
elif hasattr(request.node, 'rep_call') and \
request.node.rep_call.failed and fail_snapshot:
snapshot_name = "{0}_failed".format(default_snapshot_name)
hardware.create_snapshot(snapshot_name)
request.addfinalizer(test_fin)
@pytest.fixture(scope="function")
def underlay(request, revert_snapshot, config, hardware):
"""Fixture that should provide SSH access to underlay objects.
Input data:
- config.underlay.ssh : JSONList, *must* be provided, from 'hardware'
fixture or from an external config
:rtype UnderlaySSHManager: Object that encapsulate SSH credentials;
- provide list of underlay nodes;
- provide SSH access to underlay nodes using
node names or node IPs.
"""
# If no snapshot was reverted, then try to revert the snapshot
# that belongs to the fixture.
# Note: keep fixtures in strict dependences from each other!
if not revert_snapshot:
if hardware.has_snapshot(ext.SNAPSHOT.underlay) and \
hardware.has_snapshot_config(ext.SNAPSHOT.underlay):
hardware.revert_snapshot(ext.SNAPSHOT.underlay)
# Create Underlay
if not config.underlay.ssh:
# for devops manager: power on nodes and wait for SSH
# for empty manager: do nothing
# for maas manager: provision nodes and wait for SSH
hardware.start()
# If config.underlay.ssh wasn't provided from external config, then
# try to get necessary data from hardware manager (fuel-devops)
config.underlay.ssh = hardware.get_ssh_data(
roles=config.underlay.roles)
underlay = underlay_ssh_manager.UnderlaySSHManager(config.underlay.ssh)
if not config.underlay.lvm:
underlay.enable_lvm(hardware.lvm_storages())
config.underlay.lvm = underlay.config_lvm
hardware.create_snapshot(ext.SNAPSHOT.underlay)
else:
# 1. hardware environment created and powered on
# 2. config.underlay.ssh contains SSH access to provisioned nodes
# (can be passed from external config with TESTS_CONFIGS variable)
underlay = underlay_ssh_manager.UnderlaySSHManager(config.underlay.ssh)
return underlay