Ejemplo n.º 1
0
 def test_split_packagename(self):
     """Test splitting package name into N,E,V,R,A."""
     pkg_name = "bash-0:4.2.46-20.el7_2.x86_64.rpm"
     name, epoch, version, release, arch = utils.split_packagename(pkg_name)
     assert name == "bash"
     assert epoch == "0"
     assert version == "4.2.46"
     assert release == "20.el7_2"
     assert arch == "x86_64"
Ejemplo n.º 2
0
 def _process_input_packages(self, data, response):
     """Parse input NEVRAs and filter out unknown (or without updates) package names."""
     packages_to_process = data.get('package_list', None)
     filtered_packages_to_process = {}
     if packages_to_process is not None:
         for pkg in packages_to_process:
             response['update_list'][pkg] = {}
             name, epoch, ver, rel, arch = split_packagename(pkg)
             if name in self.db_cache.packagename2id:
                 if self.db_cache.packagename2id[name] in self.db_cache.updates_index:
                     filtered_packages_to_process[pkg] = {'parsed_nevra': (name, epoch, ver, rel, arch)}
     return filtered_packages_to_process
Ejemplo n.º 3
0
    def process_list(self, api_version, data):  # pylint: disable=unused-argument
        """
        Returns package details.

        :param data: json request parsed into data structure

        :returns: json response with package details
        """
        validate(data, JSON_SCHEMA)

        packages = data.get('package_list', None)
        packagelist = {}
        if not packages:
            return packagelist

        for pkg in packages:
            packagedata = packagelist.setdefault(pkg, {})
            name, epoch, ver, rel, arch = utils.split_packagename(pkg)
            if name in self.cache.packagename2id \
               and (epoch, ver, rel) in self.cache.evr2id \
               and arch in self.cache.arch2id:
                name_id = self.cache.packagename2id[name]
                evr_id = self.cache.evr2id[(epoch, ver, rel)]
                arch_id = self.cache.arch2id[arch]
                if (name_id, evr_id, arch_id) in self.cache.nevra2pkgid:
                    pkg_id = self.cache.nevra2pkgid[(name_id, evr_id, arch_id)]
                    pkg_detail = self.cache.package_details[pkg_id]
                    packagedata['summary'] = pkg_detail[PKG_SUMMARY]
                    packagedata['description'] = pkg_detail[PKG_DESC]
                    packagedata['source_package'] = self._get_source_package(
                        pkg_detail)
                    packagedata['repositories'] = []
                    packagedata[
                        'package_list'] = self._get_built_binary_packages(
                            pkg_id)
                    if pkg_id in self.cache.pkgid2repoids:
                        for repo_id in self.cache.pkgid2repoids[pkg_id]:
                            repodetail = self.cache.repo_detail[repo_id]
                            repodata = {
                                'label':
                                repodetail[REPO_LABEL],
                                'name':
                                repodetail[REPO_NAME],
                                'basearch':
                                utils.none2empty(repodetail[REPO_BASEARCH]),
                                'releasever':
                                utils.none2empty(repodetail[REPO_RELEASEVER])
                            }
                            packagedata['repositories'].append(repodata)
        response = {'package_list': packagelist}

        return response
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