Ejemplo n.º 1
0
def test_azure_kernel_upgrade_case_insensitive_uuid(
    session_cloud: IntegrationCloud
):
    cfg_image_spec = ImageSpecification.from_os_image()
    if (cfg_image_spec.os, cfg_image_spec.release) != ("ubuntu", "bionic"):
        pytest.skip(
            "Test only supports ubuntu:bionic not {0.os}:{0.release}".format(
                cfg_image_spec
            )
        )
    source = get_validated_source(session_cloud)
    if not source.installs_new_version():
        pytest.skip(
            "Provide CLOUD_INIT_SOURCE to install expected working cloud-init"
        )
    image_id = IMG_AZURE_UBUNTU_PRO_FIPS_BIONIC
    with session_cloud.launch(
        launch_kwargs={"image_id": image_id}
    ) as instance:
        # We can't use setup_image fixture here because we want to avoid
        # taking a snapshot or cleaning the booted machine after cloud-init
        # upgrade.
        instance.install_new_cloud_init(
            source, take_snapshot=False, clean=False
        )
        _check_iid_insensitive_across_kernel_upgrade(instance)
Ejemplo n.º 2
0
def test_upgrade_package(session_cloud: IntegrationCloud):
    if get_validated_source(session_cloud) != CloudInitSource.DEB_PACKAGE:
        not_run_message = 'Test only supports upgrading to build deb'
        if os.environ.get('TRAVIS'):
            # If this isn't running on CI, we should know
            pytest.fail(not_run_message)
        else:
            pytest.skip(not_run_message)

    launch_kwargs = {'image_id': session_cloud.released_image_id}

    with session_cloud.launch(launch_kwargs=launch_kwargs) as instance:
        instance.install_deb()
        instance.restart()
        assert instance.execute('cloud-init status --wait --long').ok
Ejemplo n.º 3
0
def _setup_custom_image(session_cloud: IntegrationCloud):
    """Like `setup_image` in conftest.py, but with customized content."""
    source = get_validated_source(session_cloud)
    if not source.installs_new_version():
        return
    client = session_cloud.launch()

    # Insert our "disable_network_activation" file here
    client.write_to_file(
        '/etc/cloud/cloud.cfg.d/99-disable-network-activation.cfg',
        'disable_network_activation: true\n',
    )

    client.install_new_cloud_init(source)
    # Even if we're keeping instances, we don't want to keep this
    # one around as it was just for image creation
    client.destroy()
Ejemplo n.º 4
0
def test_subsequent_boot_of_upgraded_package(session_cloud: IntegrationCloud):
    source = get_validated_source(session_cloud)
    if not source.installs_new_version():
        if os.environ.get('TRAVIS'):
            # If this isn't running on CI, we should know
            pytest.fail(UNSUPPORTED_INSTALL_METHOD_MSG.format(source))
        else:
            pytest.skip(UNSUPPORTED_INSTALL_METHOD_MSG.format(source))
        return  # type checking doesn't understand that skip raises

    launch_kwargs = {'image_id': session_cloud.released_image_id}

    with session_cloud.launch(launch_kwargs=launch_kwargs) as instance:
        instance.install_new_cloud_init(
            source, take_snapshot=False, clean=False
        )
        instance.restart()
        assert instance.execute('cloud-init status --wait --long').ok
Ejemplo n.º 5
0
def test_upgrade(session_cloud: IntegrationCloud):
    source = get_validated_source(session_cloud)
    if not source.installs_new_version():
        pytest.skip(
            "Install method '{}' not supported for this test".format(source))
        return  # type checking doesn't understand that skip raises

    launch_kwargs = {
        'image_id': session_cloud._get_initial_image(),
    }

    image = ImageSpecification.from_os_image()

    # Get the paths to write test logs
    output_dir = Path(session_cloud.settings.LOCAL_LOG_PATH)
    output_dir.mkdir(parents=True, exist_ok=True)
    base_filename = 'test_upgrade_{platform}_{os}_{{stage}}_{time}.log'.format(
        platform=session_cloud.settings.PLATFORM,
        os=image.release,
        time=session_start_time,
    )
    before_path = output_dir / base_filename.format(stage='before')
    after_path = output_dir / base_filename.format(stage='after')

    # Get the network cfg file
    netcfg_path = '/dev/null'
    if image.os == 'ubuntu':
        netcfg_path = '/etc/netplan/50-cloud-init.yaml'
        if image.release == 'xenial':
            netcfg_path = '/etc/network/interfaces.d/50-cloud-init.cfg'

    with session_cloud.launch(
            launch_kwargs=launch_kwargs,
            user_data=USER_DATA,
            wait=True,
    ) as instance:
        _output_to_compare(instance, before_path, netcfg_path)
        instance.install_new_cloud_init(source, take_snapshot=False)
        instance.execute('hostname something-else')
        _restart(instance)
        _output_to_compare(instance, after_path, netcfg_path)

    log.info('Wrote upgrade test logs to %s and %s', before_path, after_path)
Ejemplo n.º 6
0
def test_clean_boot_of_upgraded_package(session_cloud: IntegrationCloud):
    source = get_validated_source(session_cloud)
    if not source.installs_new_version():
        pytest.skip(UNSUPPORTED_INSTALL_METHOD_MSG.format(source))
        return  # type checking doesn't understand that skip raises
    if (ImageSpecification.from_os_image().release == 'bionic' and
            session_cloud.settings.PLATFORM == 'lxd_vm'):
        # The issues that we see on Bionic VMs don't appear anywhere
        # else, including when calling KVM directly. It likely has to
        # do with the extra lxd-agent setup happening on bionic.
        # Given that we still have Bionic covered on all other platforms,
        # the risk of skipping bionic here seems low enough.
        pytest.skip("Upgrade test doesn't run on LXD VMs and bionic")
        return

    launch_kwargs = {
        'image_id': session_cloud.released_image_id,
    }

    with session_cloud.launch(
        launch_kwargs=launch_kwargs, user_data=USER_DATA,
    ) as instance:
        # get pre values
        pre_hostname = instance.execute('hostname')
        pre_cloud_id = instance.execute('cloud-id')
        pre_result = instance.execute('cat /run/cloud-init/result.json')
        pre_network = instance.execute('cat /etc/netplan/50-cloud-init.yaml')
        pre_systemd_analyze = instance.execute('systemd-analyze')
        pre_systemd_blame = instance.execute('systemd-analyze blame')
        pre_cloud_analyze = instance.execute('cloud-init analyze show')
        pre_cloud_blame = instance.execute('cloud-init analyze blame')

        # Ensure no issues pre-upgrade
        assert not json.loads(pre_result)['v1']['errors']

        log = instance.read_from_file('/var/log/cloud-init.log')
        assert 'Traceback' not in log
        assert 'WARN' not in log

        # Upgrade and reboot
        instance.install_new_cloud_init(source, take_snapshot=False)
        instance.execute('hostname something-else')
        instance.restart()
        assert instance.execute('cloud-init status --wait --long').ok

        # 'cloud-init init' helps us understand if our pickling upgrade paths
        # have broken across re-constitution of a cached datasource. Some
        # platforms invalidate their datasource cache on reboot, so we run
        # it here to ensure we get a dirty run.
        assert instance.execute('cloud-init init').ok

        # get post values
        post_hostname = instance.execute('hostname')
        post_cloud_id = instance.execute('cloud-id')
        post_result = instance.execute('cat /run/cloud-init/result.json')
        post_network = instance.execute('cat /etc/netplan/50-cloud-init.yaml')
        post_systemd_analyze = instance.execute('systemd-analyze')
        post_systemd_blame = instance.execute('systemd-analyze blame')
        post_cloud_analyze = instance.execute('cloud-init analyze show')
        post_cloud_blame = instance.execute('cloud-init analyze blame')

        # Ensure no issues post-upgrade
        assert not json.loads(pre_result)['v1']['errors']

        log = instance.read_from_file('/var/log/cloud-init.log')
        assert 'Traceback' not in log
        assert 'WARN' not in log

        # Ensure important things stayed the same
        assert pre_hostname == post_hostname
        assert pre_cloud_id == post_cloud_id
        assert pre_result == post_result
        assert pre_network == post_network

        # Calculate and log all the boot numbers
        pre_analyze_totals = [
            x for x in pre_cloud_analyze.splitlines()
            if x.startswith('Finished stage') or x.startswith('Total Time')
        ]
        post_analyze_totals = [
            x for x in post_cloud_analyze.splitlines()
            if x.startswith('Finished stage') or x.startswith('Total Time')
        ]

        # pylint: disable=logging-format-interpolation
        LOG.info(LOG_TEMPLATE.format(
            pre_systemd_analyze=pre_systemd_analyze,
            post_systemd_analyze=post_systemd_analyze,
            pre_systemd_blame='\n'.join(pre_systemd_blame.splitlines()[:10]),
            post_systemd_blame='\n'.join(post_systemd_blame.splitlines()[:10]),
            pre_analyze_totals='\n'.join(pre_analyze_totals),
            post_analyze_totals='\n'.join(post_analyze_totals),
            pre_cloud_blame='\n'.join(pre_cloud_blame.splitlines()[:10]),
            post_cloud_blame='\n'.join(post_cloud_blame.splitlines()[:10]),
        ))
Ejemplo n.º 7
0
def test_clean_boot_of_upgraded_package(session_cloud: IntegrationCloud):
    source = get_validated_source(session_cloud)
    if not source.installs_new_version():
        pytest.skip(UNSUPPORTED_INSTALL_METHOD_MSG.format(source))
        return  # type checking doesn't understand that skip raises
    if (ImageSpecification.from_os_image().release == "bionic"
            and session_cloud.settings.PLATFORM == "lxd_vm"):
        # The issues that we see on Bionic VMs don't appear anywhere
        # else, including when calling KVM directly. It likely has to
        # do with the extra lxd-agent setup happening on bionic.
        # Given that we still have Bionic covered on all other platforms,
        # the risk of skipping bionic here seems low enough.
        pytest.skip("Upgrade test doesn't run on LXD VMs and bionic")
        return

    launch_kwargs = {
        "image_id": session_cloud.released_image_id,
    }

    with session_cloud.launch(
            launch_kwargs=launch_kwargs,
            user_data=USER_DATA,
    ) as instance:
        # get pre values
        pre_hostname = instance.execute("hostname")
        pre_cloud_id = instance.execute("cloud-id")
        pre_result = instance.execute("cat /run/cloud-init/result.json")
        pre_network = instance.execute("cat /etc/netplan/50-cloud-init.yaml")
        pre_systemd_analyze = instance.execute("systemd-analyze")
        pre_systemd_blame = instance.execute("systemd-analyze blame")
        pre_cloud_analyze = instance.execute("cloud-init analyze show")
        pre_cloud_blame = instance.execute("cloud-init analyze blame")

        # Ensure no issues pre-upgrade
        log = instance.read_from_file("/var/log/cloud-init.log")
        assert not json.loads(pre_result)["v1"]["errors"]

        try:
            verify_clean_log(log)
        except AssertionError:
            LOG.warning("There were errors/warnings/tracebacks pre-upgrade. "
                        "Any failures may be due to pre-upgrade problem")

        # Upgrade
        instance.install_new_cloud_init(source, take_snapshot=False)

        # 'cloud-init init' helps us understand if our pickling upgrade paths
        # have broken across re-constitution of a cached datasource. Some
        # platforms invalidate their datasource cache on reboot, so we run
        # it here to ensure we get a dirty run.
        assert instance.execute("cloud-init init").ok

        # Reboot
        instance.execute("hostname something-else")
        instance.restart()
        assert instance.execute("cloud-init status --wait --long").ok

        # get post values
        post_hostname = instance.execute("hostname")
        post_cloud_id = instance.execute("cloud-id")
        post_result = instance.execute("cat /run/cloud-init/result.json")
        post_network = instance.execute("cat /etc/netplan/50-cloud-init.yaml")
        post_systemd_analyze = instance.execute("systemd-analyze")
        post_systemd_blame = instance.execute("systemd-analyze blame")
        post_cloud_analyze = instance.execute("cloud-init analyze show")
        post_cloud_blame = instance.execute("cloud-init analyze blame")

        # Ensure no issues post-upgrade
        assert not json.loads(pre_result)["v1"]["errors"]

        log = instance.read_from_file("/var/log/cloud-init.log")
        verify_clean_log(log)

        # Ensure important things stayed the same
        assert pre_hostname == post_hostname
        assert pre_cloud_id == post_cloud_id
        try:
            assert pre_result == post_result
        except AssertionError:
            if instance.settings.PLATFORM == "azure":
                pre_json = json.loads(pre_result)
                post_json = json.loads(post_result)
                assert pre_json["v1"]["datasource"].startswith(
                    "DataSourceAzure")
                assert post_json["v1"]["datasource"].startswith(
                    "DataSourceAzure")
        assert pre_network == post_network

        # Calculate and log all the boot numbers
        pre_analyze_totals = [
            x for x in pre_cloud_analyze.splitlines()
            if x.startswith("Finished stage") or x.startswith("Total Time")
        ]
        post_analyze_totals = [
            x for x in post_cloud_analyze.splitlines()
            if x.startswith("Finished stage") or x.startswith("Total Time")
        ]

        # pylint: disable=logging-format-interpolation
        LOG.info(
            LOG_TEMPLATE.format(
                pre_systemd_analyze=pre_systemd_analyze,
                post_systemd_analyze=post_systemd_analyze,
                pre_systemd_blame="\n".join(
                    pre_systemd_blame.splitlines()[:10]),
                post_systemd_blame="\n".join(
                    post_systemd_blame.splitlines()[:10]),
                pre_analyze_totals="\n".join(pre_analyze_totals),
                post_analyze_totals="\n".join(post_analyze_totals),
                pre_cloud_blame="\n".join(pre_cloud_blame.splitlines()[:10]),
                post_cloud_blame="\n".join(post_cloud_blame.splitlines()[:10]),
            ))