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