Blame tests/cloud_tests/collect.py

Packit Service a04d08
# This file is part of cloud-init. See LICENSE file for license information.
Packit Service a04d08
Packit Service a04d08
"""Used to collect data from platforms during tests."""
Packit Service a04d08
Packit Service a04d08
from functools import partial
Packit Service a04d08
import os
Packit Service a04d08
Packit Service a04d08
from cloudinit import util as c_util
Packit Service a04d08
from tests.cloud_tests import (config, LOG, setup_image, util)
Packit Service a04d08
from tests.cloud_tests.stage import (PlatformComponent, run_stage, run_single)
Packit Service a04d08
from tests.cloud_tests import platforms
Packit Service a04d08
from tests.cloud_tests.testcases import base, get_test_class
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def collect_script(instance, base_dir, script, script_name):
Packit Service a04d08
    """Collect script data.
Packit Service a04d08
Packit Service a04d08
    @param instance: instance to run script on
Packit Service a04d08
    @param base_dir: base directory for output data
Packit Service a04d08
    @param script: script contents
Packit Service a04d08
    @param script_name: name of script to run
Packit Service a04d08
    @return_value: None, may raise errors
Packit Service a04d08
    """
Packit Service a04d08
    LOG.debug('running collect script: %s', script_name)
Packit Service a04d08
    (out, err, exit) = instance.run_script(
Packit Service a04d08
        script.encode(), rcs=False,
Packit Service a04d08
        description='collect: {}'.format(script_name))
Packit Service a04d08
    if err:
Packit Service a04d08
        LOG.debug("collect script %s exited '%s' and had stderr: %s",
Packit Service a04d08
                  script_name, err, exit)
Packit Service a04d08
    if not isinstance(out, bytes):
Packit Service a04d08
        raise util.PlatformError(
Packit Service a04d08
            "Collection of '%s' returned type %s, expected bytes: %s" %
Packit Service a04d08
            (script_name, type(out), out))
Packit Service a04d08
Packit Service a04d08
    c_util.write_file(os.path.join(base_dir, script_name), out)
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def collect_console(instance, base_dir):
Packit Service a04d08
    """Collect instance console log.
Packit Service a04d08
Packit Service a04d08
    @param instance: instance to get console log for
Packit Service a04d08
    @param base_dir: directory to write console log to
Packit Service a04d08
    """
Packit Service a04d08
    logfile = os.path.join(base_dir, 'console.log')
Packit Service a04d08
    LOG.debug('getting console log for %s to %s', instance.name, logfile)
Packit Service a04d08
    try:
Packit Service a04d08
        data = instance.console_log()
Packit Service a04d08
    except NotImplementedError as e:
Packit Service a04d08
        # args[0] is hacky, but thats all I see to get at the message.
Packit Service a04d08
        data = b'NotImplementedError:' + e.args[0].encode()
Packit Service a04d08
    with open(logfile, "wb") as fp:
Packit Service a04d08
        fp.write(data)
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def collect_test_data(args, snapshot, os_name, test_name):
Packit Service a04d08
    """Collect data for test case.
Packit Service a04d08
Packit Service a04d08
    @param args: cmdline arguments
Packit Service a04d08
    @param snapshot: instantiated snapshot
Packit Service a04d08
    @param test_name: name or path of test to run
Packit Service a04d08
    @return_value: tuple of results and fail count
Packit Service a04d08
    """
Packit Service a04d08
    res = ({}, 1)
Packit Service a04d08
Packit Service a04d08
    # load test config
Packit Service a04d08
    test_name_in = test_name
Packit Service a04d08
    test_name = config.path_to_name(test_name)
Packit Service a04d08
    test_config = config.load_test_config(test_name)
Packit Service a04d08
    user_data = test_config['cloud_config']
Packit Service a04d08
    test_scripts = test_config['collect_scripts']
Packit Service a04d08
    test_output_dir = os.sep.join(
Packit Service a04d08
        (args.data_dir, snapshot.platform_name, os_name, test_name))
Packit Service a04d08
Packit Service a04d08
    # if test is not enabled, skip and return 0 failures
Packit Service a04d08
    if not test_config.get('enabled', False):
Packit Service a04d08
        LOG.warning('test config %s is not enabled, skipping', test_name)
Packit Service a04d08
        return ({}, 0)
Packit Service a04d08
Packit Service a04d08
    test_class = get_test_class(
Packit Service a04d08
        config.name_to_module(test_name_in),
Packit Service a04d08
        test_data={'platform': snapshot.platform_name, 'os_name': os_name},
Packit Service a04d08
        test_conf=test_config['cloud_config'])
Packit Service a04d08
    try:
Packit Service a04d08
        test_class.maybeSkipTest()
Packit Service a04d08
    except base.SkipTest as s:
Packit Service a04d08
        LOG.warning('skipping test config %s: %s', test_name, s)
Packit Service a04d08
        return ({}, 0)
Packit Service a04d08
Packit Service a04d08
    # if testcase requires a feature flag that the image does not support,
Packit Service a04d08
    # skip the testcase with a warning
Packit Service a04d08
    req_features = test_config.get('required_features', [])
Packit Service a04d08
    if any(feature not in snapshot.features for feature in req_features):
Packit Service a04d08
        LOG.warning('test config %s requires features not supported by image, '
Packit Service a04d08
                    'skipping.\nrequired features: %s\nsupported features: %s',
Packit Service a04d08
                    test_name, req_features, snapshot.features)
Packit Service a04d08
        return ({}, 0)
Packit Service a04d08
Packit Service a04d08
    # if there are user data overrides required for this test case, apply them
Packit Service a04d08
    overrides = snapshot.config.get('user_data_overrides', {})
Packit Service a04d08
    if overrides:
Packit Service a04d08
        LOG.debug('updating user data for collect with: %s', overrides)
Packit Service a04d08
        user_data = util.update_user_data(user_data, overrides)
Packit Service a04d08
Packit Service a04d08
    # create test instance
Packit Service a04d08
    component = PlatformComponent(
Packit Service a04d08
        partial(platforms.get_instance, snapshot, user_data,
Packit Service a04d08
                block=True, start=False, use_desc=test_name),
Packit Service a04d08
        preserve_instance=args.preserve_instance)
Packit Service a04d08
Packit Service a04d08
    LOG.info('collecting test data for test: %s', test_name)
Packit Service a04d08
    with component as instance:
Packit Service a04d08
        start_call = partial(run_single, 'boot instance', partial(
Packit Service a04d08
            instance.start, wait=True, wait_for_cloud_init=True))
Packit Service a04d08
        collect_calls = [partial(run_single, 'script {}'.format(script_name),
Packit Service a04d08
                                 partial(collect_script, instance,
Packit Service a04d08
                                         test_output_dir, script, script_name))
Packit Service a04d08
                         for script_name, script in test_scripts.items()]
Packit Service a04d08
Packit Service a04d08
        res = run_stage('collect for test: {}'.format(test_name),
Packit Service a04d08
                        [start_call] + collect_calls)
Packit Service a04d08
Packit Service a04d08
        instance.shutdown()
Packit Service a04d08
        collect_console(instance, test_output_dir)
Packit Service a04d08
Packit Service a04d08
    return res
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def collect_snapshot(args, image, os_name):
Packit Service a04d08
    """Collect data for snapshot of image.
Packit Service a04d08
Packit Service a04d08
    @param args: cmdline arguments
Packit Service a04d08
    @param image: instantiated image with set up complete
Packit Service a04d08
    @return_value tuple of results and fail count
Packit Service a04d08
    """
Packit Service a04d08
    res = ({}, 1)
Packit Service a04d08
Packit Service a04d08
    component = PlatformComponent(partial(platforms.get_snapshot, image))
Packit Service a04d08
Packit Service a04d08
    LOG.debug('creating snapshot for %s', os_name)
Packit Service a04d08
    with component as snapshot:
Packit Service a04d08
        LOG.info('collecting test data for os: %s', os_name)
Packit Service a04d08
        res = run_stage(
Packit Service a04d08
            'collect test data for {}'.format(os_name),
Packit Service a04d08
            [partial(collect_test_data, args, snapshot, os_name, test_name)
Packit Service a04d08
             for test_name in args.test_config])
Packit Service a04d08
Packit Service a04d08
    return res
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def collect_image(args, platform, os_name):
Packit Service a04d08
    """Collect data for image.
Packit Service a04d08
Packit Service a04d08
    @param args: cmdline arguments
Packit Service a04d08
    @param platform: instantiated platform
Packit Service a04d08
    @param os_name: name of distro to collect for
Packit Service a04d08
    @return_value: tuple of results and fail count
Packit Service a04d08
    """
Packit Service a04d08
    res = ({}, 1)
Packit Service a04d08
Packit Service a04d08
    os_config = config.load_os_config(
Packit Service a04d08
        platform.platform_name, os_name, require_enabled=True,
Packit Service a04d08
        feature_overrides=args.feature_override)
Packit Service a04d08
    LOG.debug('os config: %s', os_config)
Packit Service a04d08
    component = PlatformComponent(
Packit Service a04d08
        partial(platforms.get_image, platform, os_config))
Packit Service a04d08
Packit Service a04d08
    LOG.info('acquiring image for os: %s', os_name)
Packit Service a04d08
    with component as image:
Packit Service a04d08
        res = run_stage('set up and collect data for os: {}'.format(os_name),
Packit Service a04d08
                        [partial(setup_image.setup_image, args, image)] +
Packit Service a04d08
                        [partial(collect_snapshot, args, image, os_name)],
Packit Service a04d08
                        continue_after_error=False)
Packit Service a04d08
Packit Service a04d08
    return res
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def collect_platform(args, platform_name):
Packit Service a04d08
    """Collect data for platform.
Packit Service a04d08
Packit Service a04d08
    @param args: cmdline arguments
Packit Service a04d08
    @param platform_name: platform to collect for
Packit Service a04d08
    @return_value: tuple of results and fail count
Packit Service a04d08
    """
Packit Service a04d08
    res = ({}, 1)
Packit Service a04d08
Packit Service a04d08
    platform_config = config.load_platform_config(
Packit Service a04d08
        platform_name, require_enabled=True)
Packit Service a04d08
    platform_config['data_dir'] = args.data_dir
Packit Service a04d08
    LOG.debug('platform config: %s', platform_config)
Packit Service a04d08
    component = PlatformComponent(
Packit Service a04d08
        partial(platforms.get_platform, platform_name, platform_config))
Packit Service a04d08
Packit Service a04d08
    LOG.info('setting up platform: %s', platform_name)
Packit Service a04d08
    with component as platform:
Packit Service a04d08
        res = run_stage('collect for platform: {}'.format(platform_name),
Packit Service a04d08
                        [partial(collect_image, args, platform, os_name)
Packit Service a04d08
                         for os_name in args.os_name])
Packit Service a04d08
Packit Service a04d08
    return res
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
def collect(args):
Packit Service a04d08
    """Entry point for collection.
Packit Service a04d08
Packit Service a04d08
    @param args: cmdline arguments
Packit Service a04d08
    @return_value: fail count
Packit Service a04d08
    """
Packit Service a04d08
    (res, failed) = run_stage(
Packit Service a04d08
        'collect data', [partial(collect_platform, args, platform_name)
Packit Service a04d08
                         for platform_name in args.platform])
Packit Service a04d08
Packit Service a04d08
    LOG.debug('collect stages: %s', res)
Packit Service a04d08
    if args.result:
Packit Service a04d08
        util.merge_results({'collect_stages': res}, args.result)
Packit Service a04d08
Packit Service a04d08
    return failed
Packit Service a04d08
Packit Service a04d08
# vi: ts=4 expandtab