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)
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
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()
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
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)
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]), ))
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]), ))