示例#1
0
 def test_dumb_update(self):
     """Test that our dumb ``apt-get update`` wrapper works."""
     if os.getuid() != 0:
         return self.skipTest("root privileges required to opt in")
     updater = AptMirrorUpdater()
     # Remove all existing package lists.
     updater.clear_package_lists()
     # Verify that package lists aren't available.
     assert not have_package_lists()
     # Run `apt-get update' to download the package lists.
     updater.dumb_update()
     # Verify that package lists are again available.
     assert have_package_lists()
示例#2
0
    def test_smart_update(self):
        """
        Test that our smart ``apt-get update`` wrapper works.

        Currently this test simply ensures coverage of the happy path.
        Ideally it will evolve to test the handled edge cases as well.
        """
        if os.getuid() != 0:
            return self.skipTest("root privileges required to opt in")
        updater = AptMirrorUpdater()
        # Remove all existing package lists.
        updater.clear_package_lists()
        # Verify that package lists aren't available.
        assert not have_package_lists()
        # Run `apt-get update' to download the package lists.
        updater.smart_update()
        # Verify that package lists are again available.
        assert have_package_lists()
    def test_debian_lts_eol_date(self):
        """
        Regression test for `issue #5`_.

        .. _issue #5: https://github.com/xolox/python-apt-mirror-updater/issues/5
        """
        updater = AptMirrorUpdater(
            distributor_id='debian',
            distribution_codename='jessie',
            architecture='amd64',
        )
        eol_expected = (time.time() >= 1593468000)
        assert updater.release_is_eol == eol_expected
 def test_dumb_update(self):
     """Test that our dumb ``apt-get update`` wrapper works."""
     if os.getuid() != 0:
         return self.skipTest("root privileges required to opt in")
     updater = AptMirrorUpdater()
     # Remove all existing package lists.
     updater.clear_package_lists()
     # Verify that package lists aren't available.
     assert not have_package_lists()
     # Run `apt-get update' to download the package lists.
     updater.dumb_update()
     # Verify that package lists are again available.
     assert have_package_lists()
    def test_smart_update(self):
        """
        Test that our smart ``apt-get update`` wrapper works.

        Currently this test simply ensures coverage of the happy path.
        Ideally it will evolve to test the handled edge cases as well.
        """
        if os.getuid() != 0:
            return self.skipTest("root privileges required to opt in")
        updater = AptMirrorUpdater()
        # Remove all existing package lists.
        updater.clear_package_lists()
        # Verify that package lists aren't available.
        assert not have_package_lists()
        # Run `apt-get update' to download the package lists.
        updater.smart_update()
        # Verify that package lists are again available.
        assert have_package_lists()
 def test_best_mirror_selection(self):
     """Test the selection of a "best" mirror."""
     updater = AptMirrorUpdater()
     assert is_mirror_url(updater.best_mirror)
 def test_mirror_ranking(self):
     """Test the ranking of discovered mirrors."""
     updater = AptMirrorUpdater()
     # Make sure that multiple discovered mirrors are available.
     assert sum(m.is_available for m in updater.ranked_mirrors) > 10
 def test_adaptive_mirror_discovery(self):
     """Test the discovery of mirrors for the current type of system."""
     updater = AptMirrorUpdater()
     assert len(updater.available_mirrors) > 10
     assert all(is_mirror_url(c.mirror_url) for c in updater.available_mirrors)
 def test_adaptive_mirror_discovery(self):
     """Test the discovery of mirrors for the current type of system."""
     updater = AptMirrorUpdater()
     assert len(updater.available_mirrors) > 10
     for candidate in updater.available_mirrors:
         self.check_mirror_url(candidate.mirror_url)
def main():
    """Command line interface for the ``apt-mirror-updater`` program."""
    # Initialize logging to the terminal and system log.
    coloredlogs.install(syslog=True)
    # Command line option defaults.
    context = LocalContext()
    updater = AptMirrorUpdater(context=context)
    limit = MAX_MIRRORS
    actions = []
    # Parse the command line arguments.
    try:
        options, arguments = getopt.getopt(sys.argv[1:], 'r:fblc:aux:m:vqh', [
            'remote-host=',
            'find-current-mirror',
            'find-best-mirror',
            'list-mirrors',
            'change-mirror',
            'auto-change-mirror',
            'update',
            'update-package-lists',
            'exclude=',
            'max=',
            'verbose',
            'quiet',
            'help',
        ])
        for option, value in options:
            if option in ('-r', '--remote-host'):
                if actions:
                    msg = "The %s option should be the first option given on the command line!"
                    raise Exception(msg % option)
                context = RemoteContext(value)
                updater = AptMirrorUpdater(context=context)
            elif option in ('-f', '--find-current-mirror'):
                actions.append(
                    functools.partial(report_current_mirror, updater))
            elif option in ('-b', '--find-best-mirror'):
                actions.append(functools.partial(report_best_mirror, updater))
            elif option in ('-l', '--list-mirrors'):
                actions.append(
                    functools.partial(report_available_mirrors, updater))
            elif option in ('-c', '--change-mirror'):
                actions.append(functools.partial(updater.change_mirror, value))
            elif option in ('-a', '--auto-change-mirror'):
                actions.append(updater.change_mirror)
            elif option in ('-u', '--update', '--update-package-lists'):
                actions.append(updater.smart_update)
            elif option in ('-x', '--exclude'):
                actions.insert(0,
                               functools.partial(updater.ignore_mirror, value))
            elif option in ('-m', '--max'):
                limit = int(value)
            elif option in ('-v', '--verbose'):
                coloredlogs.increase_verbosity()
            elif option in ('-q', '--quiet'):
                coloredlogs.decrease_verbosity()
            elif option in ('-h', '--help'):
                usage(__doc__)
                return
            else:
                assert False, "Unhandled option!"
        if not actions:
            usage(__doc__)
            return
        # Propagate options to the Python API.
        updater.max_mirrors = limit
    except Exception as e:
        warning("Error: Failed to parse command line arguments! (%s)" % e)
        sys.exit(1)
    # Perform the requested action(s).
    try:
        for callback in actions:
            callback()
    except Exception:
        logger.exception("Encountered unexpected exception! Aborting ..")
        sys.exit(1)
 def update_package_lists(self):
     """Run ``apt-get update`` (with compensation if things break)."""
     AptMirrorUpdater(context=self.context).smart_update()
def upgrade_remote_system(context, force_reboot=False):
    """
    Perform standard system maintenance tasks on a remote Debian or Ubuntu system.

    :param context: An execution context created by :mod:`executor.contexts`.

    This function performs the following system maintenance tasks:

    1. The ``apt-get update`` command is run (using the Python API
       of the :pypi:`apt-mirror-updater` program).
    2. The ``apt-get dist-upgrade`` command is run [1]_.
    3. The ``apt-get clean`` command is run.
    4. If the file ``/var/run/reboot-required`` exists (indicating that a
       reboot is required due to security updates) the remote system is
       rebooted using the Python API of the ``reboot-remote-system`` program,
       to enable automatic unlocking of remote root disk encryption.
    5. Old kernel packages are removed (using the Python API of the
       ``debuntu-kernel-manager`` program). If more than one meta package is
       installed a warning message is logged but no exception is raised.
    6. The ``apt-get autoremove --purge`` command is run to optionally [1]_
       remove any 'auto-removable' system packages.

    .. [1] Because the ``apt-get`` option ``--yes`` is not used, the operator
           will be asked to confirm using an interactive confirmation prompt.
    """
    # Run 'apt-get update' (with compensation if things break).
    updater = AptMirrorUpdater(context=context)
    updater.smart_update()
    # Run 'apt-get dist-upgrade'.
    logger.info("Upgrading system packages on %s ..", context)
    context.execute('apt-get', 'dist-upgrade', sudo=True, tty=True)
    # Run 'apt-get clean'.
    logger.info("Cleaning up downloaded archives on %s ..", context)
    context.execute('apt-get', 'clean', sudo=True)
    # Use debuntu-kernel-manager to detect when a reboot is required by package
    # upgrades or because the system isn't running on the newest kernel yet.
    kernel_manager = KernelPackageManager(
        apt_options=['--yes'],
        context=context,
    )
    if force_reboot:
        reboot_helper(kernel_manager,
                      "Rebooting %s as requested by operator ..")
    elif kernel_manager.reboot_required:
        reboot_helper(
            kernel_manager,
            "Rebooting %s because this is required by package upgrades ..")
    elif not kernel_manager.running_newest_kernel:
        reboot_helper(
            kernel_manager,
            "Rebooting %s because it's not yet running the newest kernel ..")
    # Cleanup old kernel packages after rebooting, when we're
    # most likely (average case) running on the newest kernel.
    try:
        kernel_manager.cleanup_packages()
    except CleanupError as e:
        # Don't error out when multiple meta packages are installed.
        logger.warning(e)
    # Interactively prompt to remove packages that seem to no longer be needed
    # (but never assume this to be correct: the operator needs to confirm).
    logger.info("Removing 'auto-removable' system packages ..")
    context.execute('apt-get', 'autoremove', '--purge', sudo=True, tty=True)
    logger.info("Done!")