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)
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
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)
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)
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
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
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
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
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
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
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
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
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
def install_deb_packages(progress, priority=Priority.NONE): apt_handle = AptWrapper.get_instance() apt_handle.upgrade_all(progress, priority=priority)
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
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)
def get_ind_packages(priority=Priority.NONE): apt_handle = AptWrapper.get_instance() return apt_handle.independent_packages_available(priority)
def test_apt_wrapper_double_init(apt): from kano_updater.apt_wrapper import AptWrapper dummy_wrapper = AptWrapper.get_instance() with pytest.raises(Exception): AptWrapper()
def test_apt_wrapper_init(apt): from kano_updater.apt_wrapper import AptWrapper wrapper = AptWrapper().get_instance() assert isinstance(wrapper, AptWrapper)