3 # Copyright (c) 2010, 2011 Intel, Inc.
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; version 2 of the License
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc., 59
16 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 import zypp #pylint: disable=import-error
25 if not hasattr(zypp, 'PoolQuery') or \
26 not hasattr(zypp.RepoManager, 'loadSolvFile'):
27 raise ImportError("python-zypp in host system cannot support PoolQuery or "
28 "loadSolvFile interface, please update it to enhanced "
29 "version which can be found in download.tizen.org/tools")
32 from mic.kickstart import ksparser
33 from mic.utils import misc, rpmmisc, runner, fs_related
34 from mic.utils.grabber import myurlgrab, TextProgress
35 from mic.utils.proxy import get_proxy_for
36 from mic.utils.errors import CreatorError, RepoError, RpmError
37 from mic.conf import configmgr
43 self.mirrorlist = None
45 self.proxy_username = None
46 self.proxy_password = None
50 self.autorefresh = True
51 self.keeppackages = True
54 from mic.pluginbase import BackendPlugin
55 class Zypp(BackendPlugin):
58 def __init__(self, target_arch, instroot, cachedir, strict_mode = False):
59 self.cachedir = cachedir
60 self.instroot = instroot
61 self.target_arch = target_arch
62 self.strict_mode = strict_mode
64 self.__pkgs_license = {}
65 self.__pkgs_content = {}
66 self.__pkgs_vcsinfo = {}
70 self.repo_manager = None
71 self.repo_manager_options = None
79 self.probFilterFlags = [ rpm.RPMPROB_FILTER_OLDPACKAGE,
80 rpm.RPMPROB_FILTER_REPLACEPKG ]
82 self.has_prov_query = True
83 self.install_debuginfo = False
84 # this can't be changed, it is used by zypp
85 self.tmp_file_path = '/var/tmp'
87 def doFileLogSetup(self, uid, logfile):
88 # don't do the file log for the livecd as it can lead to open fds
89 # being left and an inability to clean up after ourself
101 self.ts_pre.closeDB()
109 def _cleanupRpmdbLocks(self, installroot):
110 # cleans up temporary files left by bdb so that differing
111 # versions of rpm don't cause problems
112 for f in glob.glob(installroot + "/var/lib/rpm/__db*"):
115 def _cleanupZyppJunk(self, installroot):
117 shutil.rmtree(os.path.join(installroot, '.zypp'))
122 self._cleanupRpmdbLocks(self.instroot)
123 # '/var/tmp' is used by zypp to build cache, so make sure
125 if not os.path.exists(self.tmp_file_path ):
126 os.makedirs(self.tmp_file_path)
128 def whatObsolete(self, pkg):
129 query = zypp.PoolQuery()
130 query.addKind(zypp.ResKind.package)
131 query.addDependency(zypp.SolvAttr.obsoletes, pkg.name(), pkg.edition())
132 query.setMatchExact()
133 for pi in query.queryResults(self.Z.pool()):
137 def _zyppQueryPackage(self, pkg):
138 query = zypp.PoolQuery()
139 query.addKind(zypp.ResKind.package)
140 query.addAttribute(zypp.SolvAttr.name, pkg)
141 query.setMatchExact()
142 for pi in query.queryResults(self.Z.pool()):
146 def _splitPkgString(self, pkg):
147 sp = pkg.rsplit(".", 1)
152 sysarch = zypp.Arch(self.target_arch)
153 if not zypp.Arch(arch).compatible_with (sysarch):
158 def selectPackage(self, pkg):
159 """Select a given package or package pattern, can be specified
160 with name.arch or name* or *name
164 self.__initialize_zypp()
166 def markPoolItem(obs, pi):
168 pi.status().setToBeInstalled (zypp.ResStatus.USER)
170 obs.status().setToBeInstalled (zypp.ResStatus.USER)
173 # compare criterion: arch compatibility first, then repo
174 # priority, and version last
177 if str(a1) != str(a2):
178 if a1.compatible_with(a2):
182 # Priority of a repository is an integer value between 0 (the
183 # highest priority) and 99 (the lowest priority)
184 pr1 = int(p1.repoInfo().priority())
185 pr2 = int(p2.repoInfo().priority())
193 (e1, v1, r1) = list(map(str, [ed1.epoch(), ed1.version(), ed1.release()]))
194 (e2, v2, r2) = list(map(str, [ed2.epoch(), ed2.version(), ed2.release()]))
195 return rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
198 startx = pkg.startswith("*")
199 endx = pkg.endswith("*")
200 ispattern = startx or endx
201 name, arch = self._splitPkgString(pkg)
204 q.addKind(zypp.ResKind.package)
207 if startx and not endx:
208 pattern = '%s$' % (pkg[1:])
209 if endx and not startx:
210 pattern = '^%s' % (pkg[0:-1])
212 pattern = '%s' % (pkg[1:-1])
214 q.addAttribute(zypp.SolvAttr.name, pattern)
218 q.addAttribute(zypp.SolvAttr.name, name)
222 q.addAttribute(zypp.SolvAttr.name, pkg)
225 q.queryResults(self.Z.pool()),
226 cmp=lambda x,y: cmpEVR(zypp.asKindPackage(x), zypp.asKindPackage(y)),
228 item = zypp.asKindPackage(pitem)
229 if item.name() in list(self.excpkgs.keys()) and \
230 self.excpkgs[item.name()] == item.repoInfo().name():
232 if item.name() in list(self.incpkgs.keys()) and \
233 self.incpkgs[item.name()] != item.repoInfo().name():
237 obspkg = self.whatObsolete(item)
239 if arch == str(item.arch()):
240 pitem.status().setToBeInstalled (zypp.ResStatus.USER)
242 markPoolItem(obspkg, pitem)
246 # Can't match using package name, then search from packge
247 # provides infomation
248 if found == False and not ispattern:
249 q.addAttribute(zypp.SolvAttr.provides, pkg)
250 q.addAttribute(zypp.SolvAttr.name,'')
253 q.queryResults(self.Z.pool()),
254 cmp=lambda x,y: cmpEVR(zypp.asKindPackage(x), zypp.asKindPackage(y)),
256 item = zypp.asKindPackage(pitem)
257 if item.name() in list(self.excpkgs.keys()) and \
258 self.excpkgs[item.name()] == item.repoInfo().name():
260 if item.name() in list(self.incpkgs.keys()) and \
261 self.incpkgs[item.name()] != item.repoInfo().name():
265 obspkg = self.whatObsolete(item)
266 markPoolItem(obspkg, pitem)
272 raise CreatorError("Unable to find package: %s" % (pkg,))
274 def inDeselectPackages(self, pitem):
275 """check if specified pacakges are in the list of inDeselectPackages
277 item = zypp.asKindPackage(pitem)
279 for pkg in self.to_deselect:
280 startx = pkg.startswith("*")
281 endx = pkg.endswith("*")
282 ispattern = startx or endx
283 pkgname, pkgarch = self._splitPkgString(pkg)
286 if name == pkgname and str(item.arch()) == pkgarch:
292 if startx and name.endswith(pkg[1:]):
294 if endx and name.startswith(pkg[:-1]):
299 def deselectPackage(self, pkg):
300 """collect packages should not be installed"""
301 self.to_deselect.append(pkg)
303 def selectGroup(self, grp, include = ksparser.GROUP_DEFAULT):
304 def compareGroup(pitem):
305 item = zypp.asKindPattern(pitem)
306 return item.repoInfo().priority()
308 self.__initialize_zypp()
311 q.addKind(zypp.ResKind.pattern)
312 for pitem in sorted(q.queryResults(self.Z.pool()), key=compareGroup):
313 item = zypp.asKindPattern(pitem)
314 summary = "%s" % item.summary()
315 name = "%s" % item.name()
316 if name == grp or summary == grp:
318 pitem.status().setToBeInstalled (zypp.ResStatus.USER)
322 if include == ksparser.GROUP_REQUIRED:
323 list([self.deselectPackage(p) for p in list(grp.default_packages.keys())])
327 raise CreatorError("Unable to find pattern: %s" % (grp,))
329 def addRepository(self, name,
333 proxy_username = None,
334 proxy_password = None,
341 # TODO: Handle cost attribute for repos
343 if not self.repo_manager:
344 self.__initialize_repo_manager()
346 if not proxy and url:
347 proxy = get_proxy_for(url)
349 repo = RepositoryStub()
353 repo.proxy_username = proxy_username
354 repo.proxy_password = proxy_password
355 repo.ssl_verify = ssl_verify
356 repo.nocache = nocache
357 repo.baseurl.append(url)
360 self.incpkgs[pkg] = name
363 self.excpkgs[pkg] = name
366 repo.mirrorlist = mirrorlist
368 # Enable gpg check for verifying corrupt packages
370 if priority is not None:
371 # priority 0 has issue in RepoInfo.setPriority
372 repo.priority = priority + 1
375 repo_info = zypp.RepoInfo()
376 repo_info.setAlias(repo.name)
377 repo_info.setName(repo.name)
378 repo_info.setEnabled(repo.enabled)
379 repo_info.setAutorefresh(repo.autorefresh)
380 repo_info.setKeepPackages(repo.keeppackages)
381 baseurl = zypp.Url(repo.baseurl[0].full)
383 baseurl.setQueryParam("ssl_verify", "no")
385 host = urllib.parse.urlparse(proxy)[1]
386 # scheme, host, path, parm, query, frag = urlparse.urlparse(proxy)
388 proxyinfo = host.rsplit(":", 1)
392 if len(proxyinfo) > 1:
395 if proxy.startswith("socks") and len(proxy.rsplit(':', 1)) == 2:
396 host = proxy.rsplit(':', 1)[0]
397 port = proxy.rsplit(':', 1)[1]
399 # parse user/pass from proxy host
400 proxyinfo = host.rsplit("@", 1)
401 if len(proxyinfo) == 2:
403 # Known Issue: If password contains ":", which should be
404 # quoted, for example, use '123%3Aabc' instead of 123:abc
405 userpassinfo = proxyinfo[0].rsplit(":", 1)
406 if len(userpassinfo) == 2:
407 proxy_username = userpassinfo[0]
408 proxy_password = userpassinfo[1]
409 elif len(userpassinfo) == 1:
410 proxy_username = userpassinfo[0]
412 baseurl.setQueryParam ("proxy", host)
413 baseurl.setQueryParam ("proxyport", port)
415 baseurl.setQueryParam ("proxyuser", proxy_username)
417 baseurl.setQueryParam ("proxypass", proxy_password)
419 baseurl.setQueryParam ("proxy", "_none_")
421 self.repos.append(repo)
423 repo_info.addBaseUrl(baseurl)
425 if repo.priority is not None:
426 repo_info.setPriority(repo.priority)
428 # this hack is used to change zypp credential file location
429 # the default one is $HOME/.zypp, which cause conflicts when
430 # installing some basic packages, and the location doesn't
431 # have any interface actually, so use a tricky way anyway
433 if 'HOME' in os.environ:
434 homedir = os.environ['HOME']
435 os.environ['HOME'] = '/'
437 os.environ['HOME'] = '/'
439 self.repo_manager.addRepository(repo_info)
441 # save back the $HOME env
443 os.environ['HOME'] = homedir
445 del os.environ['HOME']
447 self.__build_repo_cache(name)
449 except RuntimeError as e:
450 raise CreatorError(str(e))
452 msger.verbose('repo: %s was added' % name)
455 def installHasFile(self, file):
458 def preInstall(self, pkg):
459 self.pre_pkgs.append(pkg)
461 def checkPackage(self, pkg):
462 self.check_pkgs.append(pkg)
464 def _get_local_packages(self):
465 """Return a list of rpm path to be local installed.
466 This is the hook where subclasses may specify a set of rpms which
467 it requires to be installed locally.
468 This returns an empty list by default.
469 Note, subclasses should usually chain up to the base class
470 implementation of this hook.
472 cropts = configmgr.create
473 if cropts['local_pkgs_path']:
474 if os.path.isdir(cropts['local_pkgs_path']):
476 os.path.join(cropts['local_pkgs_path'], '*.rpm'))
477 elif os.path.splitext(cropts['local_pkgs_path'])[-1] == '.rpm':
478 return [cropts['local_pkgs_path']]
480 def __localinst_packages(self):
481 for rpm_path in self._get_local_packages():
482 self.installLocal(rpm_path)
483 def runInstall(self, checksize = 0):
484 os.environ["HOME"] = "/"
485 os.environ["LD_PRELOAD"] = ""
486 self.buildTransaction()
487 self.__localinst_packages()
489 todo = zypp.GetResolvablesToInsDel(self.Z.pool())
490 installed_pkgs = todo._toInstall
493 for pitem in installed_pkgs:
494 if not zypp.isKindPattern(pitem) and \
495 not self.inDeselectPackages(pitem):
496 item = zypp.asKindPackage(pitem)
499 if item.name() in self.check_pkgs:
500 self.check_pkgs.remove(item.name())
502 if not self.install_debuginfo or str(item.arch()) == "noarch":
505 dipkg = self._zyppQueryPackage("%s-debuginfo" % item.name())
507 ditem = zypp.asKindPackage(dipkg)
510 msger.warning("No debuginfo rpm found for: %s" \
514 raise CreatorError('Packages absent in image: %s' % ','.join(self.check_pkgs))
516 # record all pkg and the content
517 localpkgs = list(self.localpkgs.keys())
520 if pkg.name() in localpkgs:
521 hdr = rpmmisc.readRpmHeader(self.ts, self.localpkgs[pkg.name()])
522 pkg_long_name = misc.RPM_FMT % {
525 'version': hdr['version'],
526 'release': hdr['release']
528 license = hdr['license']
531 pkg_long_name = misc.RPM_FMT % {
534 'version': pkg.edition().version(),
535 'release': pkg.edition().release()
538 license = pkg.license()
540 if license in list(self.__pkgs_license.keys()):
541 self.__pkgs_license[license].append(pkg_long_name)
543 self.__pkgs_license[license] = [pkg_long_name]
545 total_count = len(dlpkgs)
547 download_total_size = sum([int(x.downloadSize()) for x in dlpkgs])
548 localpkgs = list(self.localpkgs.keys())
550 msger.info("Checking packages cached ...")
552 # Check if it is cached locally
553 if po.name() in localpkgs:
556 local = self.getLocalPkgPath(po)
557 name = str(po.repoInfo().name())
559 repo = filter(lambda r: r.name == name, self.repos)[0]
562 nocache = repo.nocache if repo else False
564 if os.path.exists(local):
565 if nocache or self.checkPkg(local) !=0:
568 download_total_size -= int(po.downloadSize())
570 cache_avail_size = misc.get_filesystem_avail(self.cachedir)
571 if cache_avail_size < download_total_size:
572 raise CreatorError("No enough space used for downloading.")
574 # record the total size of installed pkgs
575 install_total_size = sum([int(x.installSize()) for x in dlpkgs])
576 # check needed size before actually download and install
578 # FIXME: for multiple partitions for loop type, check fails
579 # skip the check temporarily
580 #if checksize and install_total_size > checksize:
581 # raise CreatorError("No enough space used for installing, "
582 # "please resize partition size in ks file")
584 download_count = total_count - cached_count
585 msger.info("Packages: %d Total, %d Cached, %d Missed" \
586 % (total_count, cached_count, download_count))
589 if download_count > 0:
590 msger.info("Downloading packages ...")
591 self.downloadPkgs(dlpkgs, download_count)
592 except CreatorError as e:
593 raise CreatorError("Package download failed: %s" %(e,))
596 self.installPkgs(dlpkgs)
597 except (RepoError, RpmError):
599 except Exception as e:
600 raise CreatorError("Package installation failed: %s" % (e,))
602 def getVcsInfo(self):
603 if self.__pkgs_vcsinfo:
607 self.__initialize_transaction()
609 mi = self.ts.dbMatch()
611 lname = misc.RPM_FMT % {
614 'version': hdr['version'],
615 'release': hdr['release']
618 self.__pkgs_vcsinfo[lname] = hdr['VCS']
620 # if rpm not support VCS, set to None
621 self.__pkgs_vcsinfo[lname] = None
623 return self.__pkgs_vcsinfo
625 def getAllContent(self):
626 if self.__pkgs_content:
627 return self.__pkgs_content
630 self.__initialize_transaction()
632 mi = self.ts.dbMatch()
634 lname = misc.RPM_FMT % {
637 'version': hdr['version'],
638 'release': hdr['release']
640 self.__pkgs_content[lname] = hdr['FILENAMES']
642 return self.__pkgs_content
644 def getPkgsLicense(self):
645 return self.__pkgs_license
647 def getFilelist(self, pkgname):
652 self.__initialize_transaction()
654 mi = self.ts.dbMatch('name', pkgname)
656 return header['FILENAMES']
658 def __initialize_repo_manager(self):
659 if self.repo_manager:
662 # Clean up repo metadata
663 shutil.rmtree(self.cachedir + "/etc", ignore_errors = True)
664 shutil.rmtree(self.cachedir + "/solv", ignore_errors = True)
665 shutil.rmtree(self.cachedir + "/raw", ignore_errors = True)
667 zypp.KeyRing.setDefaultAccept( zypp.KeyRing.ACCEPT_UNSIGNED_FILE
668 | zypp.KeyRing.ACCEPT_VERIFICATION_FAILED
669 | zypp.KeyRing.ACCEPT_UNKNOWNKEY
670 | zypp.KeyRing.TRUST_KEY_TEMPORARILY
673 self.repo_manager_options = \
674 zypp.RepoManagerOptions(zypp.Pathname(self.instroot))
676 self.repo_manager_options.knownReposPath = \
677 zypp.Pathname(self.cachedir + "/etc/zypp/repos.d")
679 self.repo_manager_options.repoCachePath = \
680 zypp.Pathname(self.cachedir)
682 self.repo_manager_options.repoRawCachePath = \
683 zypp.Pathname(self.cachedir + "/raw")
685 self.repo_manager_options.repoSolvCachePath = \
686 zypp.Pathname(self.cachedir + "/solv")
688 self.repo_manager_options.repoPackagesCachePath = \
689 zypp.Pathname(self.cachedir + "/packages")
691 self.repo_manager = zypp.RepoManager(self.repo_manager_options)
693 def __build_repo_cache(self, name):
694 repo = self.repo_manager.getRepositoryInfo(name)
695 if self.repo_manager.isCached(repo) or not repo.enabled():
698 msger.info('Refreshing repository: %s ...' % name)
699 self.repo_manager.buildCache(repo, zypp.RepoManager.BuildIfNeeded)
701 def __initialize_zypp(self):
705 zconfig = zypp.ZConfig_instance()
707 # Set system architecture
709 zconfig.setSystemArchitecture(zypp.Arch(self.target_arch))
711 msger.info("zypp architecture is <%s>" % zconfig.systemArchitecture())
713 # repoPackagesCachePath is corrected by this
714 self.repo_manager = zypp.RepoManager(self.repo_manager_options)
715 repos = self.repo_manager.knownRepositories()
717 if not repo.enabled():
719 self.repo_manager.loadFromCache(repo)
721 self.Z = zypp.ZYppFactory_instance().getZYpp()
722 if configmgr.create['block_recommends']:
723 msger.info("zypp not install recommend packages")
724 self.Z.resolver().setOnlyRequires(True)
725 self.Z.initializeTarget(zypp.Pathname(self.instroot))
726 self.Z.target().load()
728 def buildTransaction(self):
729 if not self.Z.resolver().resolvePool():
730 probs = self.Z.resolver().problems()
732 for problem in probs:
733 msger.warning("repo problem: %s, %s" \
734 % (problem.description().decode("utf-8"),
735 problem.details().decode("utf-8")))
737 raise RepoError("found %d resolver problem, abort!" \
740 def getLocalPkgPath(self, po):
741 repoinfo = po.repoInfo()
742 cacheroot = repoinfo.packagesPath()
743 location = po.location()
744 rpmpath = str(location.filename())
745 pkgpath = "%s/%s" % (cacheroot, os.path.basename(rpmpath))
748 def installLocal(self, pkg, po=None, updateonly=False):
750 self.__initialize_transaction()
752 solvfile = "%s/.solv" % (self.cachedir)
754 rc, out = runner.runtool([fs_related.find_binary_path("rpms2solv"),
757 f = open(solvfile, "w+")
761 warnmsg = self.repo_manager.loadSolvFile(solvfile,
762 os.path.basename(pkg))
764 msger.warning(warnmsg)
768 msger.warning('Can not get %s solv data.' % pkg)
770 hdr = rpmmisc.readRpmHeader(self.ts, pkg)
771 arch = zypp.Arch(hdr['arch'])
772 sysarch = zypp.Arch(self.target_arch)
774 if arch.compatible_with (sysarch):
775 pkgname = hdr['name']
776 self.localpkgs[pkgname] = pkg
777 self.selectPackage(pkgname)
778 msger.info("Marking %s to be installed" % (pkg))
781 msger.warning("Cannot add package %s to transaction. "
782 "Not a compatible architecture: %s" \
783 % (pkg, hdr['arch']))
785 def downloadPkgs(self, package_objects, count):
786 localpkgs = list(self.localpkgs.keys())
787 progress_obj = TextProgress(count)
789 for po in package_objects:
790 if po.name() in localpkgs:
793 filename = self.getLocalPkgPath(po)
794 if os.path.exists(filename):
795 if self.checkPkg(filename) == 0:
798 dirn = os.path.dirname(filename)
799 if not os.path.exists(dirn):
802 url = self.get_url(po)
803 proxies = self.get_proxies(po)
806 filename = myurlgrab(url.full, filename, proxies, progress_obj)
811 def preinstallPkgs(self):
813 self.__initialize_transaction()
816 cb = rpmmisc.RPMInstallCallback(self.ts_pre)
817 cb.headmsg = "Preinstall"
818 installlogfile = "%s/__catched_stderr.buf" % (self.instroot)
820 # start to catch stderr output from librpm
821 msger.enable_logstderr(installlogfile)
823 errors = self.ts_pre.run(cb.callback, '')
825 msger.disable_logstderr()
826 self.ts_pre.closeDB()
829 if errors is not None:
831 msger.warning('scriptlet or other non-fatal errors occurred '
832 'during transaction.')
837 raise RepoError('Could not run transaction.')
838 def show_unresolved_dependencies_msg(self, unresolved_dependencies):
839 for pkg, need, needflags, sense, key in unresolved_dependencies:
841 package = '-'.join(pkg)
843 if needflags == rpm.RPMSENSE_LESS:
844 deppkg = ' < '.join(need)
845 elif needflags == rpm.RPMSENSE_EQUAL:
846 deppkg = ' = '.join(need)
847 elif needflags == rpm.RPMSENSE_GREATER:
848 deppkg = ' > '.join(need)
850 deppkg = '-'.join(need)
852 if sense == rpm.RPMDEP_SENSE_REQUIRES:
853 msger.warning("[%s] Requires [%s], which is not provided" \
856 elif sense == rpm.RPMDEP_SENSE_CONFLICTS:
857 msger.warning("[%s] Conflicts with [%s]" % (package, deppkg))
859 def installPkgs(self, package_objects):
861 self.__initialize_transaction()
864 self._cleanupRpmdbLocks(self.instroot)
865 self._cleanupZyppJunk(self.instroot)
868 for flag in self.probFilterFlags:
870 self.ts.setProbFilter(probfilter)
871 self.ts_pre.setProbFilter(probfilter)
873 localpkgs = list(self.localpkgs.keys())
875 for po in package_objects:
877 if pkgname in localpkgs:
878 rpmpath = self.localpkgs[pkgname]
880 rpmpath = self.getLocalPkgPath(po)
882 if not os.path.exists(rpmpath):
883 # Maybe it is a local repo
884 rpmuri = self.get_url(po)
885 if rpmuri.startswith("file:/"):
888 if not os.path.exists(rpmpath):
889 raise RpmError("Error: %s doesn't exist" % rpmpath)
891 h = rpmmisc.readRpmHeader(self.ts, rpmpath)
893 if pkgname in self.pre_pkgs:
894 msger.verbose("pre-install package added: %s" % pkgname)
895 self.ts_pre.addInstall(h, rpmpath, 'u')
897 self.ts.addInstall(h, rpmpath, 'u')
899 unresolved_dependencies = self.ts.check()
900 if not unresolved_dependencies:
902 self.preinstallPkgs()
905 cb = rpmmisc.RPMInstallCallback(self.ts)
906 installlogfile = "%s/__catched_stderr.buf" % (self.instroot)
908 # start to catch stderr output from librpm
909 msger.enable_logstderr(installlogfile)
911 errors = self.ts.run(cb.callback, '')
913 msger.disable_logstderr()
917 if errors is not None:
919 msger.warning('scriptlet or other non-fatal errors occurred '
920 'during transaction.')
922 raise CreatorError("mic failes to install some packages")
926 raise RepoError('Could not run transaction.')
929 self.show_unresolved_dependencies_msg(unresolved_dependencies)
930 raise RepoError("Unresolved dependencies, transaction failed.")
932 def __initialize_transaction(self):
934 self.ts = rpm.TransactionSet(self.instroot)
935 # Set to not verify DSA signatures.
936 self.ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
939 self.ts_pre = rpm.TransactionSet(self.instroot)
940 # Just unpack the files, don't run scripts
941 self.ts_pre.setFlags(rpm.RPMTRANS_FLAG_ALLFILES | rpm.RPMTRANS_FLAG_NOSCRIPTS)
942 # Set to not verify DSA signatures.
943 self.ts_pre.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
945 def checkPkg(self, pkg):
947 if not os.path.exists(pkg):
949 ret = rpmmisc.checkRpmIntegrity('rpm', pkg)
951 msger.warning("package %s is damaged: %s" \
952 % (os.path.basename(pkg), pkg))
956 def _add_prob_flags(self, *flags):
958 if flag not in self.probFilterFlags:
959 self.probFilterFlags.append(flag)
961 def get_proxies(self, pobj):
967 repoinfo = pobj.repoInfo()
968 reponame = "%s" % repoinfo.name()
969 repos = [r for r in self.repos if r.name == reponame]
970 repourl = str(repoinfo.baseUrls()[0])
973 proxy = repos[0].proxy
975 proxy = get_proxy_for(repourl)
977 proxies = {str(repourl.split(':')[0]): str(proxy)}
981 def get_url(self, pobj):
985 name = str(pobj.repoInfo().name())
987 repo = filter(lambda r: r.name == name, self.repos)[0]
991 location = pobj.location()
992 location = str(location.filename())
993 if location.startswith("./"):
994 location = location[2:]
996 return repo.baseurl[0].join(location)
998 def package_url(self, pkgname):
1003 (e1, v1, r1) = list(map(str, [ed1.epoch(), ed1.version(), ed1.release()]))
1004 (e2, v2, r2) = list(map(str, [ed2.epoch(), ed2.version(), ed2.release()]))
1005 return rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
1008 self.__initialize_zypp()
1010 q = zypp.PoolQuery()
1011 q.addKind(zypp.ResKind.package)
1013 q.addAttribute(zypp.SolvAttr.name, pkgname)
1014 items = sorted(q.queryResults(self.Z.pool()),
1015 cmp=lambda x,y: cmpEVR(zypp.asKindPackage(x), zypp.asKindPackage(y)),
1019 item = zypp.asKindPackage(items[0])
1020 url = self.get_url(item)
1021 proxies = self.get_proxies(item)
1022 return (url, proxies)