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 self.Z.initializeTarget(zypp.Pathname(self.instroot))
723 self.Z.target().load()
725 def buildTransaction(self):
726 if not self.Z.resolver().resolvePool():
727 probs = self.Z.resolver().problems()
729 for problem in probs:
730 msger.warning("repo problem: %s, %s" \
731 % (problem.description().decode("utf-8"),
732 problem.details().decode("utf-8")))
734 raise RepoError("found %d resolver problem, abort!" \
737 def getLocalPkgPath(self, po):
738 repoinfo = po.repoInfo()
739 cacheroot = repoinfo.packagesPath()
740 location = po.location()
741 rpmpath = str(location.filename())
742 pkgpath = "%s/%s" % (cacheroot, os.path.basename(rpmpath))
745 def installLocal(self, pkg, po=None, updateonly=False):
747 self.__initialize_transaction()
749 solvfile = "%s/.solv" % (self.cachedir)
751 rc, out = runner.runtool([fs_related.find_binary_path("rpms2solv"),
754 f = open(solvfile, "w+")
758 warnmsg = self.repo_manager.loadSolvFile(solvfile,
759 os.path.basename(pkg))
761 msger.warning(warnmsg)
765 msger.warning('Can not get %s solv data.' % pkg)
767 hdr = rpmmisc.readRpmHeader(self.ts, pkg)
768 arch = zypp.Arch(hdr['arch'])
769 sysarch = zypp.Arch(self.target_arch)
771 if arch.compatible_with (sysarch):
772 pkgname = hdr['name']
773 self.localpkgs[pkgname] = pkg
774 self.selectPackage(pkgname)
775 msger.info("Marking %s to be installed" % (pkg))
778 msger.warning("Cannot add package %s to transaction. "
779 "Not a compatible architecture: %s" \
780 % (pkg, hdr['arch']))
782 def downloadPkgs(self, package_objects, count):
783 localpkgs = list(self.localpkgs.keys())
784 progress_obj = TextProgress(count)
786 for po in package_objects:
787 if po.name() in localpkgs:
790 filename = self.getLocalPkgPath(po)
791 if os.path.exists(filename):
792 if self.checkPkg(filename) == 0:
795 dirn = os.path.dirname(filename)
796 if not os.path.exists(dirn):
799 url = self.get_url(po)
800 proxies = self.get_proxies(po)
803 filename = myurlgrab(url.full, filename, proxies, progress_obj)
808 def preinstallPkgs(self):
810 self.__initialize_transaction()
813 cb = rpmmisc.RPMInstallCallback(self.ts_pre)
814 cb.headmsg = "Preinstall"
815 installlogfile = "%s/__catched_stderr.buf" % (self.instroot)
817 # start to catch stderr output from librpm
818 msger.enable_logstderr(installlogfile)
820 errors = self.ts_pre.run(cb.callback, '')
822 msger.disable_logstderr()
823 self.ts_pre.closeDB()
826 if errors is not None:
828 msger.warning('scriptlet or other non-fatal errors occurred '
829 'during transaction.')
834 raise RepoError('Could not run transaction.')
835 def show_unresolved_dependencies_msg(self, unresolved_dependencies):
836 for pkg, need, needflags, sense, key in unresolved_dependencies:
838 package = '-'.join(pkg)
840 if needflags == rpm.RPMSENSE_LESS:
841 deppkg = ' < '.join(need)
842 elif needflags == rpm.RPMSENSE_EQUAL:
843 deppkg = ' = '.join(need)
844 elif needflags == rpm.RPMSENSE_GREATER:
845 deppkg = ' > '.join(need)
847 deppkg = '-'.join(need)
849 if sense == rpm.RPMDEP_SENSE_REQUIRES:
850 msger.warning("[%s] Requires [%s], which is not provided" \
853 elif sense == rpm.RPMDEP_SENSE_CONFLICTS:
854 msger.warning("[%s] Conflicts with [%s]" % (package, deppkg))
856 def installPkgs(self, package_objects):
858 self.__initialize_transaction()
861 self._cleanupRpmdbLocks(self.instroot)
862 self._cleanupZyppJunk(self.instroot)
865 for flag in self.probFilterFlags:
867 self.ts.setProbFilter(probfilter)
868 self.ts_pre.setProbFilter(probfilter)
870 localpkgs = list(self.localpkgs.keys())
872 for po in package_objects:
874 if pkgname in localpkgs:
875 rpmpath = self.localpkgs[pkgname]
877 rpmpath = self.getLocalPkgPath(po)
879 if not os.path.exists(rpmpath):
880 # Maybe it is a local repo
881 rpmuri = self.get_url(po)
882 if rpmuri.startswith("file:/"):
885 if not os.path.exists(rpmpath):
886 raise RpmError("Error: %s doesn't exist" % rpmpath)
888 h = rpmmisc.readRpmHeader(self.ts, rpmpath)
890 if pkgname in self.pre_pkgs:
891 msger.verbose("pre-install package added: %s" % pkgname)
892 self.ts_pre.addInstall(h, rpmpath, 'u')
894 self.ts.addInstall(h, rpmpath, 'u')
896 unresolved_dependencies = self.ts.check()
897 if not unresolved_dependencies:
899 self.preinstallPkgs()
902 cb = rpmmisc.RPMInstallCallback(self.ts)
903 installlogfile = "%s/__catched_stderr.buf" % (self.instroot)
905 # start to catch stderr output from librpm
906 msger.enable_logstderr(installlogfile)
908 errors = self.ts.run(cb.callback, '')
910 msger.disable_logstderr()
914 if errors is not None:
916 msger.warning('scriptlet or other non-fatal errors occurred '
917 'during transaction.')
919 raise CreatorError("mic failes to install some packages")
923 raise RepoError('Could not run transaction.')
926 self.show_unresolved_dependencies_msg(unresolved_dependencies)
927 raise RepoError("Unresolved dependencies, transaction failed.")
929 def __initialize_transaction(self):
931 self.ts = rpm.TransactionSet(self.instroot)
932 # Set to not verify DSA signatures.
933 self.ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
936 self.ts_pre = rpm.TransactionSet(self.instroot)
937 # Just unpack the files, don't run scripts
938 self.ts_pre.setFlags(rpm.RPMTRANS_FLAG_ALLFILES | rpm.RPMTRANS_FLAG_NOSCRIPTS)
939 # Set to not verify DSA signatures.
940 self.ts_pre.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS)
942 def checkPkg(self, pkg):
944 if not os.path.exists(pkg):
946 ret = rpmmisc.checkRpmIntegrity('rpm', pkg)
948 msger.warning("package %s is damaged: %s" \
949 % (os.path.basename(pkg), pkg))
953 def _add_prob_flags(self, *flags):
955 if flag not in self.probFilterFlags:
956 self.probFilterFlags.append(flag)
958 def get_proxies(self, pobj):
964 repoinfo = pobj.repoInfo()
965 reponame = "%s" % repoinfo.name()
966 repos = [r for r in self.repos if r.name == reponame]
967 repourl = str(repoinfo.baseUrls()[0])
970 proxy = repos[0].proxy
972 proxy = get_proxy_for(repourl)
974 proxies = {str(repourl.split(':')[0]): str(proxy)}
978 def get_url(self, pobj):
982 name = str(pobj.repoInfo().name())
984 repo = filter(lambda r: r.name == name, self.repos)[0]
988 location = pobj.location()
989 location = str(location.filename())
990 if location.startswith("./"):
991 location = location[2:]
993 return repo.baseurl[0].join(location)
995 def package_url(self, pkgname):
1000 (e1, v1, r1) = list(map(str, [ed1.epoch(), ed1.version(), ed1.release()]))
1001 (e2, v2, r2) = list(map(str, [ed2.epoch(), ed2.version(), ed2.release()]))
1002 return rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
1005 self.__initialize_zypp()
1007 q = zypp.PoolQuery()
1008 q.addKind(zypp.ResKind.package)
1010 q.addAttribute(zypp.SolvAttr.name, pkgname)
1011 items = sorted(q.queryResults(self.Z.pool()),
1012 cmp=lambda x,y: cmpEVR(zypp.asKindPackage(x), zypp.asKindPackage(y)),
1016 item = zypp.asKindPackage(items[0])
1017 url = self.get_url(item)
1018 proxies = self.get_proxies(item)
1019 return (url, proxies)