예제 #1
0
def run_updating_cache_raising_test(mocker, monkeypatch, fail_count):
    '''
    Tests that the `AptWrapper._update_cache()` function works when
    there are various download errors.

    Helper function for other tests.
    '''

    import kano_updater.monitor_heartbeat
    from kano_updater.retry import RETRIES
    heartbeat = mocker.MagicMock()
    monkeypatch.setattr(kano_updater.retry, 'heartbeat', heartbeat)

    from kano_updater.apt_progress_wrapper import AptDownloadFailException
    cache_update = mocker.MagicMock(
        side_effect=get_raising_function(fail_count, AptDownloadFailException)
    )

    from kano_updater.apt_wrapper import AptWrapper
    from kano_updater.progress import CLIProgress
    progress = CLIProgress()
    wrapper = AptWrapper.get_instance()
    monkeypatch.setattr(wrapper._cache, 'update', cache_update)

    wrapper._update_cache(progress, 5, 5)

    assert cache_update.call_count == min(EXPECTED_FAILS + 1, RETRIES)
    assert heartbeat.call_count == min(EXPECTED_FAILS + 1, RETRIES)
예제 #2
0
def install_urgent(progress, status):
    progress.split(
        Phase(
            'installing-urgent',
            _("Installing Hotfix"),
            100,
            is_main=True
        )
    )
    logger.info("Installing urgent hotfix")
    apt_handle = AptWrapper.get_instance()
    packages_to_update = apt_handle.packages_to_be_upgraded()
    progress.start('installing-urgent')
    install_deb_packages(progress, priority=Priority.URGENT)
    status.is_urgent = False
    try:
        from kano_profile.tracker import track_data
        track_data('updated_hotfix', {
            'packages': packages_to_update
        })
        logger.info("Tracking Data: '{}'".format(packages_to_update))
    except ImportError as imp_exc:
        logger.error("Couldn't track hotfix installation, failed to import "
                     "tracking module", exception=imp_exc)
    except Exception:
        pass

    return True
예제 #3
0
def run_fetch_archives_raising_test(mocker, monkeypatch, fail_count, raise_expected):
    '''
    Tests that the `AptWrapper._fetch_archives()` function works when
    there are various download errors.

    Helper function for other tests.
    '''
    import kano_updater.monitor_heartbeat
    from kano_updater.retry import RETRIES
    heartbeat = mocker.MagicMock()
    monkeypatch.setattr(kano_updater.retry, 'heartbeat', heartbeat)

    from kano_updater.apt_progress_wrapper import AptDownloadFailException
    fetch_archives = mocker.MagicMock(
        side_effect=get_raising_function(fail_count, AptDownloadFailException)
    )

    from kano_updater.apt_wrapper import AptWrapper
    from kano_updater.progress import CLIProgress
    progress = CLIProgress()
    wrapper = AptWrapper.get_instance()
    monkeypatch.setattr(wrapper._cache, 'fetch_archives', fetch_archives)

    if raise_expected:
        with pytest.raises(AptDownloadFailException):
            wrapper._fetch_archives(progress)
    else:
        wrapper._fetch_archives(progress)

    assert fetch_archives.call_count == min(EXPECTED_FAILS + 1, RETRIES)
    assert heartbeat.call_count == min(EXPECTED_FAILS + 1, RETRIES)
예제 #4
0
def _cache_deb_packages(progress, priority=Priority.NONE):
    apt_handle = AptWrapper.get_instance()

    progress.start('updating-sources')
    apt_handle.update(progress=progress)

    progress.start('downloading-apt-packages')
    apt_handle.cache_updates(progress, priority=priority)
예제 #5
0
def _cache_deb_packages(progress, priority=Priority.NONE):
    apt_handle = AptWrapper.get_instance()

    progress.start('updating-sources')
    apt_handle.update(progress=progress)

    progress.start('downloading-apt-packages')
    apt_handle.cache_updates(progress, priority=priority)
예제 #6
0
def install_ind_package(progress, package):
    status = UpdaterStatus.get_instance()
    # install an independent package.

    previous_state = status.state

    # Allow installing only if the updater is in certain safe states.
    if status.state not in [UpdaterStatus.NO_UPDATES,
                            UpdaterStatus.UPDATES_AVAILABLE,
                            UpdaterStatus.UPDATES_INSTALLED]:
        msg = "The install is already running"
        logger.warn(msg)
        progress.abort(msg)
        return False

    if package not in status.updatable_independent_packages:
        msg = "tried to install non-independent package {} using update_ind_pkg".format(package)
        logger.warn(msg)
        progress.abort(msg)
        return False

    status.state = UpdaterStatus.INSTALLING_INDEPENDENT
    status.save()

    update_sources_phase = 'updating-sources'
    installing_idp_phase = 'installing-idp-package'
    progress.split(
        Phase(
            update_sources_phase,
            _("Updating apt sources"),
            10
        ),
        Phase(
            installing_idp_phase,
            _("Installing independent package"),
            90
        )
    )

    apt_handle = AptWrapper.get_instance()

    progress.start(update_sources_phase)
    apt_handle.update(progress)

    progress.start(installing_idp_phase)
    apt_handle.upgrade(package, progress)

    status.state = previous_state
    status.last_update = int(time.time())

    # always check independent packages as NONE as urgent updates to
    # these packages are dealt with by the main updater
    status.updatable_independent_packages = get_ind_packages(Priority.NONE)
    status.is_scheduled = False
    status.save()

    progress.finish(_("Update completed"))
    return True
예제 #7
0
def install_ind_package(progress, package):
    status = UpdaterStatus.get_instance()
    # install an independent package.

    previous_state = status.state

    # Allow installing only if the updater is in certain safe states.
    if status.state not in [
            UpdaterStatus.NO_UPDATES, UpdaterStatus.UPDATES_AVAILABLE,
            UpdaterStatus.UPDATES_INSTALLED
    ]:
        msg = "The install is already running"
        logger.warn(msg)
        progress.abort(msg)
        return False

    if package not in status.updatable_independent_packages:
        msg = "tried to install non-independent package {} using update_ind_pkg".format(
            package)
        logger.warn(msg)
        progress.abort(msg)
        return False

    status.state = UpdaterStatus.INSTALLING_INDEPENDENT
    status.save()

    update_sources_phase = 'updating-sources'
    installing_idp_phase = 'installing-idp-package'
    progress.split(
        Phase(update_sources_phase, _("Updating apt sources"), 10),
        Phase(installing_idp_phase, _("Installing independent package"), 90))

    apt_handle = AptWrapper.get_instance()

    progress.start(update_sources_phase)
    apt_handle.update(progress)

    progress.start(installing_idp_phase)
    apt_handle.upgrade(package, progress)

    status.state = previous_state
    status.last_update = int(time.time())

    # always check independent packages as NONE as urgent updates to
    # these packages are dealt with by the main updater
    status.updatable_independent_packages = get_ind_packages(Priority.NONE)
    status.is_scheduled = False
    status.save()

    progress.finish(_("Update completed"))
    return True
예제 #8
0
def test_space(apt):
    from kano_updater.apt_wrapper import AptWrapper

    wrapper = AptWrapper.get_instance()
    wrapper._mark_all_for_update()

    install_req = 0
    dl_req = 0

    for pkg in wrapper._cache:
        install_req += pkg.candidate.installed_size / (1024. * 1024.)
        dl_req += pkg.candidate.size / (1024. * 1024.)

    assert wrapper.get_required_upgrade_space() == install_req + dl_req
예제 #9
0
def test_upgrade_all(apt):
    from kano_updater.apt_wrapper import AptWrapper
    from kano_updater.progress import CLIProgress

    wrapper = AptWrapper.get_instance()
    progress = CLIProgress()

    for pkg in wrapper._cache:
        if pkg.is_upgradable:
            assert pkg.installed != pkg.candidate
        else:
            assert pkg.installed == pkg.candidate

    wrapper.upgrade_all(progress=progress)

    for pkg in wrapper._cache:
        assert pkg.installed == pkg.candidate
예제 #10
0
def install_urgent(progress, status):
    progress.split(
        Phase('installing-urgent', _("Installing Hotfix"), 100, is_main=True))
    logger.debug("Installing urgent hotfix")
    apt_handle = AptWrapper.get_instance()
    packages_to_update = apt_handle.packages_to_be_upgraded()
    progress.start('installing-urgent')
    install_deb_packages(progress, priority=Priority.URGENT)
    status.is_urgent = False
    try:
        from kano_profile.tracker import track_data
        track_data('updated_hotfix', {'packages': packages_to_update})
        logger.debug("Tracking Data: '{}'".format(packages_to_update))
    except ImportError as imp_exc:
        logger.error("Couldn't track hotfix installation, failed to import " \
                     "tracking module: [{}]".format(imp_exc))
    except Exception:
        pass
예제 #11
0
def _do_check(progress, priority=Priority.NONE):
    '''
    Perform checks for all priorities greater than the one provided.
    '''
    apt_handle = AptWrapper.get_instance()

    apt_handle.update(progress, sources_list=KANO_SOURCES_LIST)
    logger.info("Checking urgent: {}".format(priority <= Priority.URGENT))
    logger.info("Checking standard: {}".format(priority <= Priority.STANDARD))
    run_cmd_log('apt-get --yes autoclean')

    if (priority <= Priority.URGENT
            and apt_handle.is_update_available(priority=Priority.URGENT)):
        return Priority.URGENT

    if (priority <= Priority.STANDARD and apt_handle.is_update_available()):
        return Priority.STANDARD

    return Priority.NONE
예제 #12
0
def check_disk_space(priority):
    '''
    Check for available disk space before updating
    '''

    from kano.utils.disk import get_free_space

    from kano_updater.apt_wrapper import AptWrapper

    apt_handle = AptWrapper.get_instance()
    mb_free = get_free_space()
    required_space = apt_handle.get_required_upgrade_space() + SPACE_BUFFER

    logger.info('Final upgrade required size is {} MB'.format(required_space))

    if mb_free < required_space:
        err_msg = N_("Only {}MB free, at least {}MB is needed.").format(
            mb_free, required_space
        )
        return False, err_msg

    return True, None
예제 #13
0
def check_disk_space(priority):
    '''
    Check for available disk space before updating
    '''

    apt_handle = AptWrapper.get_instance()
    mb_free = get_free_space()
    required_space = apt_handle.get_required_upgrade_space() + SPACE_BUFFER

    # Allowance for installing extra packages in the postupdate scenarios
    # during the update to 3.8.0
    system_version = get_system_version()
    if system_version < OSVersion.from_version_string("Kanux-Beta-3.8.0"):
        required_space += UPGRADE_3_8_0_SPACE

    required_space = max(required_space, MIN_REQ_SPACE)

    if mb_free < required_space:
        err_msg = N_("Only {}MB free, at least {}MB is needed.").format(
            mb_free, required_space)

        return False, err_msg

    return True, None
예제 #14
0
def _do_check(progress, priority=Priority.NONE):
    '''
    Perform checks for all priorities greater than the one provided.
    '''
    apt_handle = AptWrapper.get_instance()

    apt_handle.update(progress, sources_list=KANO_SOURCES_LIST)
    logger.info("Checking urgent: {}".format(priority <= Priority.URGENT))
    logger.info("Checking standard: {}".format(priority <= Priority.STANDARD))
    run_cmd_log('apt-get --yes autoclean')

    if (
            priority <= Priority.URGENT
            and apt_handle.is_update_available(priority=Priority.URGENT)
        ):
        return Priority.URGENT

    if (
            priority <= Priority.STANDARD
            and apt_handle.is_update_available()
        ):
        return Priority.STANDARD

    return Priority.NONE
예제 #15
0
def install_deb_packages(progress, priority=Priority.NONE):
    apt_handle = AptWrapper.get_instance()
    apt_handle.upgrade_all(progress, priority=priority)
예제 #16
0
def install_standard(progress, status):
    progress.split(
        Phase(
            'init',
            _("Starting Update"),
            10,
            is_main=True
        ),
        Phase(
            'updating-itself',
            _("Updating Itself"),
            10,
            is_main=True
        ),
        Phase(
            'preupdate',
            _("Running The Preupdate Scripts"),
            10,
            is_main=True
        ),
        Phase(
            'updating-deb-packages',
            _("Updating Deb Packages"),
            30,
            is_main=True
        ),
        Phase(
            'postupdate',
            _("Running The Postupdate Scripts"),
            10,
            is_main=True
        ),
        Phase(
            'aux-tasks',
            _("Performing auxiliary tasks"),
            10,
            is_main=True
        )
    )

    progress.start('init')
    apt_handle = AptWrapper.get_instance()
    apt_handle.clear_cache()
    apt_handle.fix_broken(progress)

    # determine the versions (from and to)
    system_version = get_system_version()
    target_version = get_target_version()

    msg = "Upgrading from {} to {}".format(system_version, target_version)
    logger.info(msg)

    # set up the scenarios and check whether they cover updating
    # from this version
    preup = PreUpdate(system_version)
    postup = PostUpdate(system_version)
    if not (preup.covers_update() and postup.covers_update()):
        title = _("Unfortunately, your version of Kano OS is too old "
                  "to be updated through the updater.")
        description = _("You will need to download the image of the "
                        "OS and reflash your SD card.")

        msg = "{}: {}".format(title, description)
        logger.error("Updating from a version that is no longer supported ({})"
                     .format(system_version))
        progress.fail(msg)
        raise InstallError(msg)

    old_updater = apt_handle.get_package('kano-updater').installed.version

    progress.start('updating-itself')
    apt_handle.upgrade('kano-updater', progress)

    # relaunch if the updater has changed
    new_updater = apt_handle.get_package('kano-updater')
    if old_updater != new_updater.installed.version:
        # Remove the installation in progress status so it doesn't
        # block the start of the new instance.
        status.state = UpdaterStatus.UPDATES_DOWNLOADED
        status.save()

        logger.info("The updater has been updated, relaunching.")
        progress.relaunch()
        return False

    progress.start('preupdate')
    try:
        preup.run(progress)
    except Relaunch:
        progress.relaunch()
        return False
    except Exception as e:
        logger.error("The pre-update scenarios failed", exception=e)
        progress.abort("The pre-update tasks failed.")
        raise

    logger.info("Updating deb packages")
    progress.start('updating-deb-packages')
    install_deb_packages(progress)

    progress.start('postupdate')
    try:
        postup.run(progress)
    except Relaunch:
        bump_system_version()
        progress.relaunch()
        return False
    except Exception as e:
        logger.error("The post-update scenarios failed", exception=e)
        progress.abort("The post-update tasks failed.")
        raise

    bump_system_version()

    # We don't care too much when these fail
    progress.start('aux-tasks')
    run_aux_tasks(progress)

    return True
예제 #17
0
def install_standard(progress, status):
    progress.split(
        Phase('init', _("Starting Update"), 10, is_main=True),
        Phase('updating-itself', _("Updating Itself"), 10, is_main=True),
        Phase('preupdate',
              _("Running The Preupdate Scripts"),
              10,
              is_main=True),
        Phase('updating-deb-packages',
              _("Updating Deb Packages"),
              30,
              is_main=True),
        Phase('postupdate',
              _("Running The Postupdate Scripts"),
              10,
              is_main=True),
        Phase('aux-tasks', _("Performing auxiliary tasks"), 10, is_main=True))

    progress.start('init')
    apt_handle = AptWrapper.get_instance()
    apt_handle.clear_cache()
    apt_handle.fix_broken(progress)

    # determine the versions (from and to)
    system_version = get_system_version()
    target_version = get_target_version()

    msg = "Upgrading from {} to {}".format(system_version, target_version)
    logger.info(msg)

    # set up the scenarios and check whether they cover updating
    # from this version
    preup = PreUpdate(system_version)
    postup = PostUpdate(system_version)
    if not (preup.covers_update() and postup.covers_update()):
        title = _("Unfortunately, your version of Kano OS is too old " \
                  "to be updated through the updater.")
        description = _("You will need to download the image of the " \
                        "OS and reflash your SD card.")

        msg = "{}: {}".format(title, description)
        logger.error(
            "Updating from a version that is no longer supported ({})".format(
                system_version))
        progress.fail(msg)
        raise InstallError(msg)

    old_updater = apt_handle.get_package('kano-updater').installed.version

    progress.start('updating-itself')
    apt_handle.upgrade('kano-updater', progress)

    # relaunch if the updater has changed
    new_updater = apt_handle.get_package('kano-updater')
    if old_updater != new_updater.installed.version:
        # Remove the installation in progress status so it doesn't
        # block the start of the new instance.
        status.state = UpdaterStatus.UPDATES_DOWNLOADED
        status.save()

        logger.info("The updater has been updated, relaunching.")
        progress.relaunch()
        return False

    progress.start('preupdate')
    try:
        preup.run()
    except Exception as err:
        logger.error("The pre-update scenarios failed.")
        logger.error(err.encode('utf-8'))
        progress.abort("The pre-update tasks failed.")
        raise

    logger.debug("Updating deb packages")
    progress.start('updating-deb-packages')
    install_deb_packages(progress)

    progress.start('postupdate')
    try:
        postup.run()
    except Exception as err:
        logger.error("The post-update scenarios failed.")
        logger.error(err.encode('utf-8'))
        progress.abort("The post-update tasks failed.")
        raise

    bump_system_version()

    # We don't care too much when these fail
    progress.start('aux-tasks')
    run_aux_tasks(progress)
예제 #18
0
def install_deb_packages(progress, priority=Priority.NONE):
    apt_handle = AptWrapper.get_instance()
    apt_handle.upgrade_all(progress, priority=priority)
예제 #19
0
def get_ind_packages(priority=Priority.NONE):
    apt_handle = AptWrapper.get_instance()
    return apt_handle.independent_packages_available(priority)
예제 #20
0
def test_apt_wrapper_double_init(apt):
    from kano_updater.apt_wrapper import AptWrapper
    dummy_wrapper = AptWrapper.get_instance()

    with pytest.raises(Exception):
        AptWrapper()
예제 #21
0
def get_ind_packages(priority=Priority.NONE):
    apt_handle = AptWrapper.get_instance()
    return apt_handle.independent_packages_available(priority)
예제 #22
0
def test_apt_wrapper_init(apt):
    from kano_updater.apt_wrapper import AptWrapper
    wrapper = AptWrapper().get_instance()

    assert isinstance(wrapper, AptWrapper)