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)
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
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"
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