Exemple #1
0
        def got_server_uuid(server_uuid):

            warning = "Couldn't determine which hash=>id database to use: %s"

            if server_uuid is None:
                logging.warning(warning % "server UUID not available")
                return None

            try:
                lsb_release_info = parse_lsb_release(self.lsb_release_filename)
            except IOError as error:
                logging.warning(warning % str(error))
                return None
            try:
                codename = lsb_release_info["code-name"]
            except KeyError:
                logging.warning(warning % "missing code-name key in %s" %
                                self.lsb_release_filename)
                return None

            arch = self._facade.get_arch()
            if not arch:
                # The Apt code should always return a non-empty string,
                # so this branch shouldn't get executed at all. However
                # this check is kept as an extra paranoia sanity check.
                logging.warning(warning % "unknown dpkg architecture")
                return None

            return os.path.join(self._config.hash_id_directory,
                                "%s_%s_%s" % (server_uuid, codename, arch))
Exemple #2
0
 def test_parse_lsb_release_with_missing_or_extra_fields(self):
     """
     L{parse_lsb_release} ignores lines not matching the map of
     known keys, and returns only keys with an actual value.
     """
     lsb_release_filename = self.makeFile("DISTRIB_ID=Ubuntu\n" "FOO=Bar\n")
     self.assertEqual(parse_lsb_release(lsb_release_filename),
                      {"distributor-id": "Ubuntu"})
        def got_server_uuid(server_uuid):

            warning = "Couldn't determine which hash=>id database to use: %s"

            if server_uuid is None:
                logging.warning(warning % "server UUID not available")
                return None

            try:
                lsb_release_info = parse_lsb_release(self.lsb_release_filename)
            except IOError, error:
                logging.warning(warning % str(error))
                return None
Exemple #4
0
    def test_parse_lsb_release(self):
        """
        L{parse_lsb_release} returns a C{dict} holding information from
        the given LSB release file.
        """
        lsb_release_filename = self.makeFile("DISTRIB_ID=Ubuntu\n"
                                             "DISTRIB_RELEASE=6.06\n"
                                             "DISTRIB_CODENAME=dapper\n"
                                             "DISTRIB_DESCRIPTION="
                                             "\"Ubuntu 6.06.1 LTS\"\n")

        self.assertEqual(
            parse_lsb_release(lsb_release_filename), {
                "distributor-id": "Ubuntu",
                "description": "Ubuntu 6.06.1 LTS",
                "release": "6.06",
                "code-name": "dapper"
            })
Exemple #5
0
    def handle_release_upgrade(self, message):
        """Fetch the upgrade-tool, verify it and run it.

        @param message: A message of type C{"release-upgrade"}.
        """
        target_code_name = message["code-name"]
        operation_id = message["operation-id"]
        lsb_release_info = parse_lsb_release(self.lsb_release_filename)
        current_code_name = lsb_release_info["code-name"]

        if target_code_name == current_code_name:
            message = self.make_operation_result_message(
                operation_id, FAILED,
                "The system is already running %s." % target_code_name, 1)
            logging.info("Queuing message with release upgrade failure to "
                         "exchange urgently.")
            return self._send_message(message)

        tarball_url = message["upgrade-tool-tarball-url"]
        signature_url = message["upgrade-tool-signature-url"]
        allow_third_party = message.get("allow-third-party", False)
        debug = message.get("debug", False)
        directory = self._config.upgrade_tool_directory
        tarball_filename = url_to_filename(tarball_url, directory=directory)
        signature_filename = url_to_filename(signature_url,
                                             directory=directory)

        result = self.fetch(tarball_url, signature_url)
        result.addCallback(
            lambda x: self.verify(tarball_filename, signature_filename))
        result.addCallback(lambda x: self.extract(tarball_filename))
        result.addCallback(lambda x: self.tweak(current_code_name))
        result.addCallback(
            lambda x: self.upgrade(target_code_name,
                                   operation_id,
                                   allow_third_party=allow_third_party,
                                   debug=debug))
        result.addCallback(lambda x: self.finish())
        result.addErrback(self.abort, operation_id)
        return result
Exemple #6
0
    def _compute_packages_changes(self):
        """Analyse changes in the universe of known packages.

        This method will verify if there are packages that:

        - are now installed, and were not;
        - are now available, and were not;
        - are now locked, and were not;
        - were previously available but are not anymore;
        - were previously installed but are not anymore;
        - were previously locked but are not anymore;

        Additionally it will report package locks that:

        - are now set, and were not;
        - were previously set but are not anymore;

        Also, packages coming from the security pocket will be
        reported as such.

        In all cases, the server is notified of the new situation
        with a "packages" message.

        @return: A deferred resulting in C{True} if package changes were
            detected with respect to the previous run, or C{False} otherwise.
        """
        self._facade.ensure_channels_reloaded()

        old_installed = set(self._store.get_installed())
        old_available = set(self._store.get_available())
        old_upgrades = set(self._store.get_available_upgrades())
        old_locked = set(self._store.get_locked())
        old_autoremovable = set(self._store.get_autoremovable())
        old_security = set(self._store.get_security())

        current_installed = set()
        current_available = set()
        current_upgrades = set()
        current_locked = set()
        current_autoremovable = set()
        current_security = set()
        lsb = parse_lsb_release(LSB_RELEASE_FILENAME)
        backports_archive = "{}-backports".format(lsb["code-name"])
        security_archive = "{}-security".format(lsb["code-name"])

        for package in self._facade.get_packages():
            # Don't include package versions from the official backports
            # archive. The backports archive is enabled by default since
            # xenial with a pinning policy of 100. Ideally we would
            # support pinning, but we don't yet. In the mean time, we
            # ignore backports, so that packages don't get automatically
            # upgraded to the backports version.
            backport_origins = [
                origin for origin in package.origins
                if origin.archive == backports_archive]
            if backport_origins and (
                    len(backport_origins) == len(package.origins)):
                # Ignore the version if it's only in the official
                # backports archive. If it's somewhere else as well,
                # e.g. a PPA, we assume it was added manually and the
                # user wants to get updates from it.
                continue
            hash = self._facade.get_package_hash(package)
            id = self._store.get_hash_id(hash)
            if id is not None:
                if self._facade.is_package_installed(package):
                    current_installed.add(id)
                    if self._facade.is_package_available(package):
                        current_available.add(id)
                    if self._facade.is_package_autoremovable(package):
                        current_autoremovable.add(id)
                else:
                    current_available.add(id)

                # Are there any packages that this package is an upgrade for?
                if self._facade.is_package_upgrade(package):
                    current_upgrades.add(id)

                # Is this package present in the security pocket?
                security_origins = any(
                    origin for origin in package.origins
                    if origin.archive == security_archive)
                if security_origins:
                    current_security.add(id)

        for package in self._facade.get_locked_packages():
            hash = self._facade.get_package_hash(package)
            id = self._store.get_hash_id(hash)
            if id is not None:
                current_locked.add(id)

        new_installed = current_installed - old_installed
        new_available = current_available - old_available
        new_upgrades = current_upgrades - old_upgrades
        new_locked = current_locked - old_locked
        new_autoremovable = current_autoremovable - old_autoremovable
        new_security = current_security - old_security

        not_installed = old_installed - current_installed
        not_available = old_available - current_available
        not_upgrades = old_upgrades - current_upgrades
        not_locked = old_locked - current_locked
        not_autoremovable = old_autoremovable - current_autoremovable
        not_security = old_security - current_security

        message = {}
        if new_installed:
            message["installed"] = \
                list(sequence_to_ranges(sorted(new_installed)))
        if new_available:
            message["available"] = \
                list(sequence_to_ranges(sorted(new_available)))
        if new_upgrades:
            message["available-upgrades"] = \
                list(sequence_to_ranges(sorted(new_upgrades)))
        if new_locked:
            message["locked"] = \
                list(sequence_to_ranges(sorted(new_locked)))

        if new_autoremovable:
            message["autoremovable"] = list(
                sequence_to_ranges(sorted(new_autoremovable)))
        if not_autoremovable:
            message["not-autoremovable"] = list(
                sequence_to_ranges(sorted(not_autoremovable)))

        if new_security:
            message["security"] = list(
                sequence_to_ranges(sorted(new_security)))
        if not_security:
            message["not-security"] = list(
                sequence_to_ranges(sorted(not_security)))

        if not_installed:
            message["not-installed"] = \
                list(sequence_to_ranges(sorted(not_installed)))
        if not_available:
            message["not-available"] = \
                list(sequence_to_ranges(sorted(not_available)))
        if not_upgrades:
            message["not-available-upgrades"] = \
                list(sequence_to_ranges(sorted(not_upgrades)))
        if not_locked:
            message["not-locked"] = \
                list(sequence_to_ranges(sorted(not_locked)))

        if not message:
            return succeed(False)

        message["type"] = "packages"
        result = self.send_message(message)

        logging.info(
            "Queuing message with changes in known packages: "
            "%(installed)d installed, %(available)d available, "
            "%(upgrades)d available upgrades, %(locked)d locked, "
            "%(auto)d autoremovable, %(security)d security, "
            "%(not_installed)d not installed, "
            "%(not_available)d not available, "
            "%(not_upgrades)d not available upgrades, "
            "%(not_locked)d not locked, "
            "%(not_auto)d not autoremovable, "
            "%(not_security)d not security.",
            dict(
                installed=len(new_installed), available=len(new_available),
                upgrades=len(new_upgrades), locked=len(new_locked),
                auto=len(new_autoremovable), not_installed=len(not_installed),
                not_available=len(not_available),
                not_upgrades=len(not_upgrades), not_locked=len(not_locked),
                not_auto=len(not_autoremovable), security=len(new_security),
                not_security=len(not_security)))

        def update_currently_known(result):
            if new_installed:
                self._store.add_installed(new_installed)
            if not_installed:
                self._store.remove_installed(not_installed)
            if new_available:
                self._store.add_available(new_available)
            if new_locked:
                self._store.add_locked(new_locked)
            if new_autoremovable:
                self._store.add_autoremovable(new_autoremovable)
            if not_available:
                self._store.remove_available(not_available)
            if new_upgrades:
                self._store.add_available_upgrades(new_upgrades)
            if not_upgrades:
                self._store.remove_available_upgrades(not_upgrades)
            if not_locked:
                self._store.remove_locked(not_locked)
            if not_autoremovable:
                self._store.remove_autoremovable(not_autoremovable)
            if new_security:
                self._store.add_security(new_security)
            if not_security:
                self._store.remove_security(not_security)
            # Something has changed wrt the former run, let's update the
            # timestamp and return True.
            stamp_file = self._config.detect_package_changes_stamp
            touch_file(stamp_file)
            return True

        result.addCallback(update_currently_known)

        return result
Exemple #7
0
 def _get_distribution_info(self):
     """Get details about the distribution."""
     message = {}
     message.update(parse_lsb_release(self._lsb_release_filename))
     return message