Пример #1
0
def setup_image(args, image):
    """
    set up image as specified in args
    args: cmdline arguments
    image: cloud_tests.image instance to operate on
    return_value: tuple of results and fail count
    """
    # mapping of setup cmdline arg name to setup function
    # represented as a tuple rather than a dict or odict as lookup by name not
    # needed, and order is important as --script and --upgrade go at the end
    handlers = (
        # arg   handler     description
        ('deb', install_deb, 'setup func for --deb, install deb'),
        ('rpm', install_rpm, 'setup func for --rpm, install rpm'),
        ('repo', enable_repo, 'setup func for --repo, enable repo'),
        ('ppa', enable_ppa, 'setup func for --ppa, enable ppa'),
        ('script', run_script, 'setup func for --script, run script'),
        ('upgrade', upgrade, 'setup func for --upgrade, upgrade pkgs'),
    )

    # determine which setup functions needed
    calls = [
        partial(stage.run_single, desc, partial(func, args, image))
        for name, func, desc in handlers if getattr(args, name, None)
    ]

    image_name = 'image: distro={}, release={}'.format(
        image.properties['os'], image.properties['release'])
    LOG.info('setting up %s', image_name)
    return stage.run_stage('set up for {}'.format(image_name),
                           calls,
                           continue_after_error=False)
Пример #2
0
 def __exit__(self, etype, value, trace):
     """Destroy instance."""
     if self.instance is not None:
         if self.preserve_instance:
             LOG.info('Preserving test instance %s', self.instance.name)
         else:
             self.instance.destroy()
Пример #3
0
def collect_image(args, platform, os_name):
    """
    collect data for image
    args: cmdline arguments
    platform: instantiated platform
    os_name: name of distro to collect for
    return_value: tuple of results and fail count
    """
    res = ({}, 1)

    os_config = config.load_os_config(os_name)
    if not os_config.get('enabled'):
        raise ValueError('OS {} not enabled'.format(os_name))

    component = PlatformComponent(
        partial(images.get_image, platform, os_config))

    LOG.info('acquiring image for os: %s', os_name)
    with component as image:
        res = run_stage('set up and collect data for os: {}'.format(os_name),
                        [partial(setup_image.setup_image, args, image)] +
                        [partial(collect_snapshot, args, image, os_name)],
                        continue_after_error=False)

    return res
Пример #4
0
def collect_image(args, platform, os_name):
    """Collect data for image.

    @param args: cmdline arguments
    @param platform: instantiated platform
    @param os_name: name of distro to collect for
    @return_value: tuple of results and fail count
    """
    res = ({}, 1)

    os_config = config.load_os_config(
        platform.platform_name, os_name, require_enabled=True,
        feature_overrides=args.feature_override)
    LOG.debug('os config: %s', os_config)
    component = PlatformComponent(
        partial(platforms.get_image, platform, os_config))

    LOG.info('acquiring image for os: %s', os_name)
    with component as image:
        res = run_stage('set up and collect data for os: {}'.format(os_name),
                        [partial(setup_image.setup_image, args, image)] +
                        [partial(collect_snapshot, args, image, os_name)],
                        continue_after_error=False)

    return res
Пример #5
0
def collect_image(args, platform, os_name):
    """Collect data for image.

    @param args: cmdline arguments
    @param platform: instantiated platform
    @param os_name: name of distro to collect for
    @return_value: tuple of results and fail count
    """
    res = ({}, 1)

    os_config = config.load_os_config(
        platform.platform_name, os_name, require_enabled=True,
        feature_overrides=args.feature_override)
    LOG.debug('os config: %s', os_config)
    component = PlatformComponent(
        partial(platforms.get_image, platform, os_config))

    LOG.info('acquiring image for os: %s', os_name)
    with component as image:
        res = run_stage('set up and collect data for os: {}'.format(os_name),
                        [partial(setup_image.setup_image, args, image)] +
                        [partial(collect_snapshot, args, image, os_name)],
                        continue_after_error=False)

    return res
def setup_image(args, image):
    """Set up image as specified in args.

    @param args: cmdline arguments
    @param image: cloud_tests.image instance to operate on
    @return_value: tuple of results and fail count
    """
    # update the args if necessary for this image
    overrides = image.setup_overrides
    LOG.debug('updating args for setup with: %s', overrides)
    args = util.update_args(args, overrides, preserve_old=True)

    # mapping of setup cmdline arg name to setup function
    # represented as a tuple rather than a dict or odict as lookup by name not
    # needed, and order is important as --script and --upgrade go at the end
    handlers = (
        # arg   handler     description
        ('deb', install_deb, 'setup func for --deb, install deb'),
        ('rpm', install_rpm, 'setup func for --rpm, install rpm'),
        ('repo', enable_repo, 'setup func for --repo, enable repo'),
        ('ppa', enable_ppa, 'setup func for --ppa, enable ppa'),
        ('script', run_script, 'setup func for --script, run script'),
        ('upgrade', upgrade, 'setup func for --upgrade, upgrade cloud-init'),
        ('upgrade-full', upgrade_full, 'setup func for --upgrade-full'),
    )

    # determine which setup functions needed
    calls = [partial(stage.run_single, desc, partial(func, args, image))
             for name, func, desc in handlers if getattr(args, name, None)]

    LOG.info('setting up %s', image)
    res = stage.run_stage(
        'set up for {}'.format(image), calls, continue_after_error=False)
    return res
Пример #7
0
def collect_test_data(args, snapshot, os_name, test_name):
    """Collect data for test case.

    @param args: cmdline arguments
    @param snapshot: instantiated snapshot
    @param test_name: name or path of test to run
    @return_value: tuple of results and fail count
    """
    res = ({}, 1)

    # load test config
    test_name = config.path_to_name(test_name)
    test_config = config.load_test_config(test_name)
    user_data = test_config['cloud_config']
    test_scripts = test_config['collect_scripts']
    test_output_dir = os.sep.join(
        (args.data_dir, snapshot.platform_name, os_name, test_name))

    # if test is not enabled, skip and return 0 failures
    if not test_config.get('enabled', False):
        LOG.warning('test config %s is not enabled, skipping', test_name)
        return ({}, 0)

    # if testcase requires a feature flag that the image does not support,
    # skip the testcase with a warning
    req_features = test_config.get('required_features', [])
    if any(feature not in snapshot.features for feature in req_features):
        LOG.warning('test config %s requires features not supported by image, '
                    'skipping.\nrequired features: %s\nsupported features: %s',
                    test_name, req_features, snapshot.features)
        return ({}, 0)

    # if there are user data overrides required for this test case, apply them
    overrides = snapshot.config.get('user_data_overrides', {})
    if overrides:
        LOG.debug('updating user data for collect with: %s', overrides)
        user_data = util.update_user_data(user_data, overrides)

    # create test instance
    component = PlatformComponent(
        partial(platforms.get_instance, snapshot, user_data,
                block=True, start=False, use_desc=test_name))

    LOG.info('collecting test data for test: %s', test_name)
    with component as instance:
        start_call = partial(run_single, 'boot instance', partial(
            instance.start, wait=True, wait_for_cloud_init=True))
        collect_calls = [partial(run_single, 'script {}'.format(script_name),
                                 partial(collect_script, instance,
                                         test_output_dir, script, script_name))
                         for script_name, script in test_scripts.items()]

        console_log = partial(
            run_single, 'collect console',
            partial(collect_console, instance, test_output_dir))

        res = run_stage('collect for test: {}'.format(test_name),
                        [start_call] + collect_calls + [console_log])

    return res
Пример #8
0
def bddeb(args):
    """Entry point for build deb.

    @param args: cmdline arguments
    @return_value: fail count
    """
    LOG.info('preparing to build cloud-init deb')
    (res, failed) = run_stage('build deb', [partial(setup_build, args)])
    return failed
Пример #9
0
def bddeb(args):
    """Entry point for build deb.

    @param args: cmdline arguments
    @return_value: fail count
    """
    LOG.info('preparing to build cloud-init deb')
    _res, failed = run_stage('build deb', [partial(setup_build, args)])
    return failed
Пример #10
0
def collect_test_data(args, snapshot, os_name, test_name):
    """
    collect data for test case
    args: cmdline arguments
    snapshot: instantiated snapshot
    test_name: name or path of test to run
    return_value: tuple of results and fail count
    """
    res = ({}, 1)

    # load test config
    test_name = config.path_to_name(test_name)
    test_config = config.load_test_config(test_name)
    user_data = test_config['cloud_config']
    test_scripts = test_config['collect_scripts']
    test_output_dir = os.sep.join(
        (args.data_dir, snapshot.platform_name, os_name, test_name))
    boot_timeout = (test_config.get('boot_timeout') if isinstance(
        test_config.get('boot_timeout'), int) else
                    snapshot.config.get('timeout'))

    # if test is not enabled, skip and return 0 failures
    if not test_config.get('enabled', False):
        LOG.warning('test config %s is not enabled, skipping', test_name)
        return ({}, 0)

    # create test instance
    component = PlatformComponent(
        partial(instances.get_instance,
                snapshot,
                user_data,
                block=True,
                start=False,
                use_desc=test_name))

    LOG.info('collecting test data for test: %s', test_name)
    with component as instance:
        start_call = partial(
            run_single, 'boot instance',
            partial(instance.start, wait=True, wait_time=boot_timeout))
        collect_calls = [
            partial(
                run_single, 'script {}'.format(script_name),
                partial(collect_script, instance, test_output_dir, script,
                        script_name))
            for script_name, script in test_scripts.items()
        ]

        res = run_stage('collect for test: {}'.format(test_name),
                        [start_call] + collect_calls)

    return res
Пример #11
0
def generate_ssh_keys(data_dir):
    """Generate SSH keys to be used with image."""
    LOG.info('generating SSH keys')
    filename = os.path.join(data_dir, 'id_rsa')

    if os.path.exists(filename):
        c_util.del_file(filename)

    c_util.subp([
        'ssh-keygen', '-t', 'rsa', '-b', '4096', '-f', filename, '-P', '',
        '-C', 'ubuntu@cloud_test'
    ],
                capture=True)
Пример #12
0
def collect_snapshot(args, image, os_name):
    """
    collect data for snapshot of image
    args: cmdline arguments
    image: instantiated image with set up complete
    return_value tuple of results and fail count
    """
    res = ({}, 1)

    component = PlatformComponent(partial(snapshots.get_snapshot, image))

    LOG.debug('creating snapshot for %s', os_name)
    with component as snapshot:
        LOG.info('collecting test data for os: %s', os_name)
        res = run_stage('collect test data for {}'.format(os_name), [
            partial(collect_test_data, args, snapshot, os_name, test_name)
            for test_name in args.test_config
        ])

    return res
Пример #13
0
def collect_snapshot(args, image, os_name):
    """Collect data for snapshot of image.

    @param args: cmdline arguments
    @param image: instantiated image with set up complete
    @return_value tuple of results and fail count
    """
    res = ({}, 1)

    component = PlatformComponent(partial(platforms.get_snapshot, image))

    LOG.debug('creating snapshot for %s', os_name)
    with component as snapshot:
        LOG.info('collecting test data for os: %s', os_name)
        res = run_stage(
            'collect test data for {}'.format(os_name),
            [partial(collect_test_data, args, snapshot, os_name, test_name)
             for test_name in args.test_config])

    return res
Пример #14
0
def verify(args):
    """Verify test data.

    @param args: directory of test data
    @return_value: 0 for success, or number of failed tests
    """
    failed = 0
    res = {}

    # find test data
    tests = util.list_test_data(args.data_dir)

    for platform in tests.keys():
        res[platform] = {}
        for os_name in tests[platform].keys():
            test_name = "platform='{}', os='{}'".format(platform, os_name)
            LOG.info('test: %s verifying test data', test_name)

            # run test
            res[platform][os_name] = verify_data(
                os.sep.join((args.data_dir, platform, os_name)),
                tests[platform][os_name])

            # handle results
            fail_list = [
                k for k, v in res[platform][os_name].items()
                if not v.get('passed')
            ]
            if len(fail_list) == 0:
                LOG.info('test: %s passed all tests', test_name)
            else:
                LOG.warning('test: %s failed %s tests', test_name,
                            len(fail_list))
            failed += len(fail_list)

    # dump results
    LOG.debug('verify results: %s', res)
    if args.result:
        util.merge_results({'verify': res}, args.result)

    return failed
Пример #15
0
def setup_image(args, image):
    """Set up image as specified in args.

    @param args: cmdline arguments
    @param image: cloud_tests.image instance to operate on
    @return_value: tuple of results and fail count
    """
    # update the args if necessary for this image
    overrides = image.setup_overrides
    LOG.debug('updating args for setup with: %s', overrides)
    args = util.update_args(args, overrides, preserve_old=True)

    # mapping of setup cmdline arg name to setup function
    # represented as a tuple rather than a dict or odict as lookup by name not
    # needed, and order is important as --script and --upgrade go at the end
    handlers = (
        # arg   handler     description
        ('deb', install_deb, 'setup func for --deb, install deb'),
        ('rpm', install_rpm, 'setup func for --rpm, install rpm'),
        ('repo', enable_repo, 'setup func for --repo, enable repo'),
        ('ppa', enable_ppa, 'setup func for --ppa, enable ppa'),
        ('script', run_script, 'setup func for --script, run script'),
        ('upgrade', upgrade, 'setup func for --upgrade, upgrade cloud-init'),
        ('upgrade-full', upgrade_full, 'setup func for --upgrade-full'),
    )

    # determine which setup functions needed
    calls = [partial(stage.run_single, desc, partial(func, args, image))
             for name, func, desc in handlers if getattr(args, name, None)]

    try:
        data = yaml.load(image.read_data("/etc/cloud/build.info", decode=True))
        info = ' '.join(["%s=%s" % (k, data.get(k))
                         for k in ("build_name", "serial") if k in data])
    except Exception as e:
        info = "N/A (%s)" % e

    LOG.info('setting up %s (%s)', image, info)
    res = stage.run_stage(
        'set up for {}'.format(image), calls, continue_after_error=False)
    return res
Пример #16
0
def collect_platform(args, platform_name):
    """Collect data for platform.

    @param args: cmdline arguments
    @param platform_name: platform to collect for
    @return_value: tuple of results and fail count
    """
    res = ({}, 1)

    platform_config = config.load_platform_config(platform_name,
                                                  require_enabled=True)
    component = PlatformComponent(
        partial(platforms.get_platform, platform_name, platform_config))

    LOG.info('setting up platform: %s', platform_name)
    with component as platform:
        res = run_stage('collect for platform: {}'.format(platform_name), [
            partial(collect_image, args, platform, os_name)
            for os_name in args.os_name
        ])

    return res
Пример #17
0
def verify(args):
    """Verify test data.

    @param args: directory of test data
    @return_value: 0 for success, or number of failed tests
    """
    failed = 0
    res = {}

    # find test data
    tests = util.list_test_data(args.data_dir)

    for platform in tests.keys():
        res[platform] = {}
        for os_name in tests[platform].keys():
            test_name = "platform='{}', os='{}'".format(platform, os_name)
            LOG.info('test: %s verifying test data', test_name)

            # run test
            res[platform][os_name] = verify_data(
                args.data_dir, platform, os_name,
                tests[platform][os_name])

            # handle results
            fail_list = [k for k, v in res[platform][os_name].items()
                         if not v.get('passed')]
            if len(fail_list) == 0:
                LOG.info('test: %s passed all tests', test_name)
            else:
                LOG.warning('test: %s failed %s tests', test_name,
                            len(fail_list))
            failed += len(fail_list)

    # dump results
    LOG.debug('\n---- Verify summarized results:\n%s', format_results(res))
    if args.result:
        util.merge_results({'verify': res}, args.result)

    return failed
Пример #18
0
def collect_platform(args, platform_name):
    """Collect data for platform.

    @param args: cmdline arguments
    @param platform_name: platform to collect for
    @return_value: tuple of results and fail count
    """
    res = ({}, 1)

    platform_config = config.load_platform_config(
        platform_name, require_enabled=True)
    platform_config['data_dir'] = args.data_dir
    LOG.debug('platform config: %s', platform_config)
    component = PlatformComponent(
        partial(platforms.get_platform, platform_name, platform_config))

    LOG.info('setting up platform: %s', platform_name)
    with component as platform:
        res = run_stage('collect for platform: {}'.format(platform_name),
                        [partial(collect_image, args, platform, os_name)
                         for os_name in args.os_name])

    return res
Пример #19
0
def collect_platform(args, platform_name):
    """
    collect data for platform
    args: cmdline arguments
    platform_name: platform to collect for
    return_value: tuple of results and fail count
    """
    res = ({}, 1)

    platform_config = config.load_platform_config(platform_name)
    if not platform_config.get('enabled'):
        raise ValueError('Platform {} not enabled'.format(platform_name))

    component = PlatformComponent(
        partial(platforms.get_platform, platform_name, platform_config))

    LOG.info('setting up platform: %s', platform_name)
    with component as platform:
        res = run_stage('collect for platform: {}'.format(platform_name), [
            partial(collect_image, args, platform, os_name)
            for os_name in args.os_name
        ])

    return res
Пример #20
0
def setup_build(args):
    """Set build system up then run build.

    @param args: cmdline arguments
    @return_value: tuple of results and fail count
    """
    res = ({}, 1)

    # set up platform
    LOG.info('setting up platform: %s', args.build_platform)
    platform_config = config.load_platform_config(args.build_platform)
    platform_call = partial(platforms.get_platform, args.build_platform,
                            platform_config)
    with PlatformComponent(platform_call) as platform:

        # set up image
        LOG.info('acquiring image for os: %s', args.build_os)
        img_conf = config.load_os_config(platform.platform_name, args.build_os)
        image_call = partial(images.get_image, platform, img_conf)
        with PlatformComponent(image_call) as image:

            # set up snapshot
            snapshot_call = partial(snapshots.get_snapshot, image)
            with PlatformComponent(snapshot_call) as snapshot:

                # create instance with cloud-config to set it up
                LOG.info('creating instance to build deb in')
                empty_cloud_config = "#cloud-config\n{}"
                instance_call = partial(instances.get_instance,
                                        snapshot,
                                        empty_cloud_config,
                                        use_desc='build cloud-init deb')
                with PlatformComponent(instance_call) as instance:

                    # build the deb
                    res = run_single('build deb on system',
                                     partial(build_deb, args, instance))

    return res
Пример #21
0
def setup_build(args):
    """Set build system up then run build.

    @param args: cmdline arguments
    @return_value: tuple of results and fail count
    """
    res = ({}, 1)

    # set up platform
    LOG.info('setting up platform: %s', args.build_platform)
    platform_config = config.load_platform_config(args.build_platform)
    platform_call = partial(platforms.get_platform, args.build_platform,
                            platform_config)
    with PlatformComponent(platform_call) as platform:

        # set up image
        LOG.info('acquiring image for os: %s', args.build_os)
        img_conf = config.load_os_config(platform.platform_name, args.build_os)
        image_call = partial(platforms.get_image, platform, img_conf)
        with PlatformComponent(image_call) as image:

            # set up snapshot
            snapshot_call = partial(platforms.get_snapshot, image)
            with PlatformComponent(snapshot_call) as snapshot:

                # create instance with cloud-config to set it up
                LOG.info('creating instance to build deb in')
                empty_cloud_config = "#cloud-config\n{}"
                instance_call = partial(
                    platforms.get_instance, snapshot, empty_cloud_config,
                    use_desc='build cloud-init deb')
                with PlatformComponent(instance_call) as instance:

                    # build the deb
                    res = run_single('build deb on system',
                                     partial(build_deb, args, instance))

    return res
Пример #22
0
def collect_test_data(args, snapshot, os_name, test_name):
    """Collect data for test case.

    @param args: cmdline arguments
    @param snapshot: instantiated snapshot
    @param test_name: name or path of test to run
    @return_value: tuple of results and fail count
    """
    res = ({}, 1)

    # load test config
    test_name_in = test_name
    test_name = config.path_to_name(test_name)
    test_config = config.load_test_config(test_name)
    user_data = test_config['cloud_config']
    test_scripts = test_config['collect_scripts']
    test_output_dir = os.sep.join(
        (args.data_dir, snapshot.platform_name, os_name, test_name))

    # if test is not enabled, skip and return 0 failures
    if not test_config.get('enabled', False):
        LOG.warning('test config %s is not enabled, skipping', test_name)
        return ({}, 0)

    test_class = get_test_class(
        config.name_to_module(test_name_in),
        test_data={'platform': snapshot.platform_name, 'os_name': os_name},
        test_conf=test_config['cloud_config'])
    try:
        test_class.maybeSkipTest()
    except base.SkipTest as s:
        LOG.warning('skipping test config %s: %s', test_name, s)
        return ({}, 0)

    # if testcase requires a feature flag that the image does not support,
    # skip the testcase with a warning
    req_features = test_config.get('required_features', [])
    if any(feature not in snapshot.features for feature in req_features):
        LOG.warning('test config %s requires features not supported by image, '
                    'skipping.\nrequired features: %s\nsupported features: %s',
                    test_name, req_features, snapshot.features)
        return ({}, 0)

    # if there are user data overrides required for this test case, apply them
    overrides = snapshot.config.get('user_data_overrides', {})
    if overrides:
        LOG.debug('updating user data for collect with: %s', overrides)
        user_data = util.update_user_data(user_data, overrides)

    # create test instance
    component = PlatformComponent(
        partial(platforms.get_instance, snapshot, user_data,
                block=True, start=False, use_desc=test_name),
        preserve_instance=args.preserve_instance)

    LOG.info('collecting test data for test: %s', test_name)
    with component as instance:
        start_call = partial(run_single, 'boot instance', partial(
            instance.start, wait=True, wait_for_cloud_init=True))
        collect_calls = [partial(run_single, 'script {}'.format(script_name),
                                 partial(collect_script, instance,
                                         test_output_dir, script, script_name))
                         for script_name, script in test_scripts.items()]

        res = run_stage('collect for test: {}'.format(test_name),
                        [start_call] + collect_calls)

        instance.shutdown()
        collect_console(instance, test_output_dir)

    return res
Пример #23
0
 def __exit__(self, etype, value, trace):
     """Destroy tempdir if no errors occurred."""
     if etype or self.preserve:
         LOG.info('leaving data in %s', self.tmpdir)
     else:
         shutil.rmtree(self.tmpdir)