Ejemplo n.º 1
0
 def _build_nevra(self, update_pkg_id):
     name_id, evr_id, arch_id, _, _, _ = self.db_cache.package_details[
         update_pkg_id]
     name = self.db_cache.id2packagename[name_id]
     epoch, ver, rel = self.db_cache.id2evr[evr_id]
     arch = self.db_cache.id2arch[arch_id]
     return join_packagename(name, epoch, ver, rel, arch)
Ejemplo n.º 2
0
 def get_package_list_for_erratum_id(self, oid):
     """
     Get the list of packages for the given erratum id
     """
     pkg_query = """SELECT package.name, evr.epoch, evr.version, evr.release, arch.name
                      FROM pkg_errata
                      JOIN package ON package.id = pkg_errata.pkg_id
                      JOIN evr ON evr.id = package.evr_id
                      JOIN arch ON arch.id = package.arch_id
                     WHERE pkg_errata.errata_id = %s"""
     self.cursor.execute(pkg_query, (oid, ))
     result = self.cursor.fetchall()
     package_list = []
     for name, epoch, version, release, arch in result:
         package_list.append(
             join_packagename(name, epoch, version, release, arch))
     return package_list
Ejemplo n.º 3
0
 def test_join_pkgname(self):
     """Test joining package name"""
     pkg_name = utils.join_packagename("test", "2", "1.2", "4.el7",
                                       "x86_64")
     assert pkg_name == "test-2:1.2-4.el7.x86_64"
Ejemplo n.º 4
0
    def process_list(self, data):
        #pylint: disable=too-many-locals,too-many-branches,too-many-statements,too-many-nested-blocks
        """
        This method is looking for updates of a package, including name of package to update to,
        associated erratum and repository this erratum is from.

        :param packages_to_process: list of package to find updates for every of them

        :returns: updates for a package in format of list of dictionaries {'package': <p_name>, 'erratum': <e_name>,
        'repository': <r_label>}

        """
        # pylint: disable=invalid-name
        packages_to_process = data['package_list']
        auxiliary_dict = {}
        answer = {}

        if not packages_to_process:
            return answer

        provided_repo_ids = None
        provided_repo_labels = None

        if 'repository_list' in data:
            provided_repo_labels = data['repository_list']

            if provided_repo_labels:
                provided_repo_ids = []
                self.cursor.execute("select id from repo where label in %s;",
                                    [tuple(provided_repo_labels)])
                for id_tuple in self.cursor.fetchall():
                    for oid in id_tuple:
                        provided_repo_ids.append(oid)

        packages_names = []
        packages_evrids = []

        for pkg in packages_to_process:
            pkg = str(pkg)

            # process all packages form input
            if pkg not in auxiliary_dict:
                n, e, v, r, a = split_packagename(str(pkg))
                auxiliary_dict[pkg] = {
                }  # fill auxiliary dictionary with empty data for every package
                answer[pkg] = []  # fill answer with empty data

                evr_key = "%s:%s:%s" % (e, v, r)
                if evr_key in self.evr2id_dict and a in self.arch2id_dict:
                    packages_names.append(n)
                    auxiliary_dict[pkg][n] = []

                    evr_id = self.evr2id_dict[evr_key]
                    packages_evrids.append(evr_id)
                    auxiliary_dict[pkg]['evr_id'] = evr_id
                    auxiliary_dict[pkg]['arch_id'] = self.arch2id_dict[a]
                    auxiliary_dict[pkg]['repo_id'] = []
                    auxiliary_dict[pkg]['pkg_id'] = []
                    auxiliary_dict[pkg]['update_id'] = []

        response = {
            'update_list': answer,
        }

        if provided_repo_ids is not None:
            response.update({'repository_list': provided_repo_labels})

        if not packages_evrids:
            return response

        # Select all packages with given evrs ids and put them into dictionary
        self.cursor.execute(
            "select id, name, evr_id, arch_id from package where evr_id in %s;",
            [tuple(packages_evrids)])
        packs = self.cursor.fetchall()
        nevra2pkg_id = {}
        for oid, name, evr_id, arch_id in packs:
            key = "%s:%s:%s" % (name, evr_id, arch_id)
            if key not in nevra2pkg_id:
                nevra2pkg_id[key] = [oid]
            else:
                nevra2pkg_id[key].append(oid)

        pkg_ids = []
        for pkg in auxiliary_dict:
            n, e, v, r, a = split_packagename(str(pkg))

            try:
                key = "%s:%s:%s" % (n, auxiliary_dict[pkg]['evr_id'],
                                    auxiliary_dict[pkg]['arch_id'])
                pkg_ids.extend(nevra2pkg_id[key])
                auxiliary_dict[pkg]['pkg_id'].extend(nevra2pkg_id[key])
            except KeyError:
                pass

        if not pkg_ids:
            return response

        # Select all repo_id and add mapping to package id
        self.cursor.execute(
            "select pkg_id, repo_id from pkg_repo where pkg_id in %s;",
            [tuple(pkg_ids)])
        pack_repo_ids = self.cursor.fetchall()
        pkg_id2repo_id = {}

        repo_ids = []

        for pkg_id, repo_id in pack_repo_ids:
            repo_ids.append(repo_id)

            if pkg_id in pkg_id2repo_id:
                pkg_id2repo_id[pkg_id].append(repo_id)
            else:
                pkg_id2repo_id[pkg_id] = [repo_id]

        for pkg in auxiliary_dict:
            try:
                for pkg_id in auxiliary_dict[pkg]['pkg_id']:
                    auxiliary_dict[pkg]['repo_id'].extend(
                        pkg_id2repo_id[pkg_id])
            except KeyError:
                pass

        self.cursor.execute("select name, id from package where name in %s;",
                            [tuple(packages_names)])
        sql_result = self.cursor.fetchall()
        names2ids = {}
        for name, oid in sql_result:

            if name in names2ids:
                names2ids[name].append(oid)
            else:
                names2ids[name] = [oid]

        for pkg in auxiliary_dict:
            n, e, v, r, a = split_packagename(str(pkg))

            try:
                auxiliary_dict[pkg][n].extend(names2ids[n])
            except KeyError:
                pass

        update_pkg_ids = []

        sql = """SELECT package.id
                   FROM package
                   JOIN evr ON package.evr_id = evr.id
                  WHERE package.id in %s and evr.evr > (select evr from evr where id = %s)"""
        for pkg in auxiliary_dict:
            n, e, v, r, a = split_packagename(str(pkg))

            if n in auxiliary_dict[pkg] and auxiliary_dict[pkg][n]:
                self.cursor.execute(sql, [
                    tuple(auxiliary_dict[pkg][n]),
                    auxiliary_dict[pkg]['evr_id']
                ])

                for oid in self.cursor.fetchall():
                    auxiliary_dict[pkg]['update_id'].append(oid[0])
                    update_pkg_ids.append(oid[0])

        # Select all info about repos
        self.cursor.execute("select id, label, url from repo where id in %s;",
                            [tuple(repo_ids)])
        all_repos = self.cursor.fetchall()
        repoinfo_dict = {}
        for oid, label, url in all_repos:
            repoinfo_dict[oid] = {'label': label, 'url': url}

        pkg_id2repo_id = {}
        pkg_id2errata_id = {}
        pkg_id2full_name = {}
        pkg_id2arch_id = {}
        all_errata = []

        if update_pkg_ids:
            # Select all info about pkg_id to repo_id for update packages
            self.cursor.execute(
                "select pkg_id, repo_id from pkg_repo where pkg_id in %s;",
                [tuple(update_pkg_ids)])
            all_pkg_repos = self.cursor.fetchall()
            for pkg_id, repo_id in all_pkg_repos:

                if pkg_id not in pkg_id2repo_id:
                    pkg_id2repo_id[pkg_id] = [repo_id]
                else:
                    pkg_id2repo_id[pkg_id].append(repo_id)

            # Select all info about pkg_id to errata_id
            self.cursor.execute(
                "select pkg_id, errata_id from pkg_errata where pkg_id in %s;",
                [tuple(update_pkg_ids)])
            all_pkg_errata = self.cursor.fetchall()
            for pkg_id, errata_id in all_pkg_errata:
                all_errata.append(errata_id)
                if pkg_id not in pkg_id2errata_id:
                    pkg_id2errata_id[pkg_id] = [errata_id]
                else:
                    pkg_id2errata_id[pkg_id].append(errata_id)

            # Select full info about all update packages
            self.cursor.execute(
                "SELECT id, name, evr_id, arch_id from package where id in %s;",
                [tuple(update_pkg_ids)])
            packages = self.cursor.fetchall()

            for oid, name, evr_id, arch_id in packages:
                full_rpm_name = join_packagename(
                    name, self.id2evr_dict[evr_id]['epoch'],
                    self.id2evr_dict[evr_id]['version'],
                    self.id2evr_dict[evr_id]['release'],
                    self.id2arch_dict[arch_id])

                pkg_id2full_name[oid] = full_rpm_name
                pkg_id2arch_id[oid] = arch_id

        if all_errata:
            # Select all info about errata
            self.cursor.execute("SELECT id, name from errata where id in %s;",
                                [tuple(all_errata)])
            errata = self.cursor.fetchall()
            id2errata_dict = {}
            all_errata_id = []
            for oid, name in errata:
                id2errata_dict[oid] = name
                all_errata_id.append(oid)

            self.cursor.execute(
                "SELECT errata_id, repo_id from errata_repo where errata_id in %s",
                [tuple(all_errata_id)])
            sql_result = self.cursor.fetchall()
            errata_id2repo_id = {}
            for errata_id, repo_id in sql_result:
                if errata_id not in errata_id2repo_id:
                    errata_id2repo_id[errata_id] = [repo_id]
                else:
                    errata_id2repo_id[errata_id].append(repo_id)

            self.cursor.execute(
                "SELECT errata_id, cve_id from errata_cve where errata_id in %s",
                [tuple(all_errata_id)])
            sql_result = self.cursor.fetchall()
            errata_id2cve_id = {}
            for errata_id, cve_id in sql_result:
                if errata_id not in errata_id2cve_id:
                    errata_id2cve_id[errata_id] = [cve_id]
                else:
                    errata_id2cve_id[errata_id].append(cve_id)

        # Fill the result answer with update information
        for pkg in auxiliary_dict:
            if 'update_id' not in auxiliary_dict[pkg]:
                continue

            for upd_pkg_id in auxiliary_dict[pkg]['update_id']:
                # FIXME: use compatibility tables instead of exact matching
                if auxiliary_dict[pkg]['arch_id'] == pkg_id2arch_id[
                        upd_pkg_id]:
                    for r_id in pkg_id2repo_id[upd_pkg_id]:
                        # check if update package in the same repo with original one
                        # and if the list of repositories for updates is provided, also check repo id in this list
                        if r_id in auxiliary_dict[pkg]['repo_id'] and \
                                (provided_repo_ids is None or r_id in provided_repo_ids):
                            # Some pkgs don't have associated errata (eg, original-repo-content)
                            if upd_pkg_id in pkg_id2errata_id:
                                errata_ids = pkg_id2errata_id[upd_pkg_id]
                                for e_id in errata_ids:
                                    # check current erratum has some linked cve
                                    if e_id in errata_id2cve_id and errata_id2cve_id[
                                            e_id]:
                                        # check current errata in the same repo with update pkg
                                        if r_id in errata_id2repo_id[e_id]:
                                            e_name = id2errata_dict[e_id]
                                            r_label = repoinfo_dict[r_id][
                                                'label']

                                            response['update_list'][
                                                pkg].append({
                                                    'package':
                                                    pkg_id2full_name[
                                                        upd_pkg_id],
                                                    'erratum':
                                                    e_name,
                                                    'repository':
                                                    r_label
                                                })

        return response