From 9f9a62dd634fbdba3954ce28149d40250f81f564 Mon Sep 17 00:00:00 2001 From: Gui Chen Date: Fri, 13 Apr 2012 10:26:04 +0800 Subject: [PATCH] pre-install package support with zypp use '%prepackages' in ks file to specify the packages needed to be pre-installed, pre-installing would not run with scriptlet, and it's only used for zypp now. Signed-off-by: Gui Chen --- mic/imager/baseimager.py | 9 +++++++ mic/kickstart/__init__.py | 21 ++++++++++++++++ mic/utils/rpmmisc.py | 3 ++- plugins/backend/yumpkgmgr.py | 4 ++++ plugins/backend/zypppkgmgr.py | 56 ++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 91 insertions(+), 2 deletions(-) diff --git a/mic/imager/baseimager.py b/mic/imager/baseimager.py index 1658a04..83bdc01 100644 --- a/mic/imager/baseimager.py +++ b/mic/imager/baseimager.py @@ -834,6 +834,14 @@ class BaseImageCreator(object): for rpm_path in self._get_local_packages(): pkg_manager.installLocal(rpm_path) + def __preinstall_packages(self, pkg_manager): + if not self.ks: + return + + self._preinstall_pkgs = kickstart.get_pre_packages(self.ks) + for pkg in self._preinstall_pkgs: + pkg_manager.preInstall(pkg) + def install(self, repo_urls = {}): """Install packages into the install root. @@ -882,6 +890,7 @@ class BaseImageCreator(object): try: try: + self.__preinstall_packages(pkg_manager) self.__select_packages(pkg_manager) self.__select_groups(pkg_manager) self.__deselect_packages(pkg_manager) diff --git a/mic/kickstart/__init__.py b/mic/kickstart/__init__.py index 36e8feb..d306fb3 100644 --- a/mic/kickstart/__init__.py +++ b/mic/kickstart/__init__.py @@ -25,6 +25,7 @@ import string from mic import msger from mic.utils import errors, misc, runner, fs_related as fs +import pykickstart.sections as kssections import pykickstart.commands as kscommands import pykickstart.constants as ksconstants import pykickstart.errors as kserrors @@ -38,6 +39,21 @@ import custom_commands.moblinrepo as moblinrepo import custom_commands.micboot as micboot import custom_commands.partition as partition +class PrepackageSection(kssections.Section): + sectionOpen = "%prepackages" + + def handleLine(self, line): + if not self.handler: + return + + (h, s, t) = line.partition('#') + line = h.rstrip() + + self.handler.prepackages.add([line]) + + def handleHeader(self, lineno, args): + kssections.Section.handleHeader(self, lineno, args) + def read_kickstart(path): """Parse a kickstart file and return a KickstartParser instance. @@ -64,8 +80,10 @@ def read_kickstart(path): class KSHandlers(superclass): def __init__(self, mapping={}): superclass.__init__(self, mapping=commandMap[using_version]) + self.prepackages = ksparser.Packages() ks = ksparser.KickstartParser(KSHandlers()) + ks.registerSection(PrepackageSection(ks.handler)) try: ks.readKickstart(path) @@ -734,6 +752,9 @@ def convert_method_to_repo(ks): except (AttributeError, kserrors.KickstartError): pass +def get_pre_packages(ks, required = []): + return ks.handler.prepackages.packageList + required + def get_packages(ks, required = []): return ks.handler.packages.packageList + required diff --git a/mic/utils/rpmmisc.py b/mic/utils/rpmmisc.py index ed63dc2..fd25fe8 100644 --- a/mic/utils/rpmmisc.py +++ b/mic/utils/rpmmisc.py @@ -109,6 +109,7 @@ class RPMInstallCallback: self.ts = ts self.filelog = False self.logString = [] + self.headmsg = "Installing" def _dopkgtup(self, hdr): tmpepoch = hdr['epoch'] @@ -217,7 +218,7 @@ class RPMInstallCallback: pkgname = os.path.basename(rpmloc) if self.output and (sys.stdout.isatty() or self.total_installed == self.total_actions): fmt = self._makefmt(percent) - msg = fmt % ("Installing", pkgname) + msg = fmt % (self.headmsg, pkgname) if msg != self.lastmsg: self.lastmsg = msg diff --git a/plugins/backend/yumpkgmgr.py b/plugins/backend/yumpkgmgr.py index b855034..efa26bd 100644 --- a/plugins/backend/yumpkgmgr.py +++ b/plugins/backend/yumpkgmgr.py @@ -173,6 +173,10 @@ class Yum(BackendPlugin, yum.YumBase): self.doRepoSetup() self.doSackSetup() + def preInstall(self, pkg): + # FIXME: handle pre-install package + return None + def selectPackage(self, pkg): """Select a given package. Can be specified with name.arch or name* diff --git a/plugins/backend/zypppkgmgr.py b/plugins/backend/zypppkgmgr.py index a700dc4..8df1f6d 100755 --- a/plugins/backend/zypppkgmgr.py +++ b/plugins/backend/zypppkgmgr.py @@ -66,9 +66,12 @@ class Zypp(BackendPlugin): self.repo_manager_options = None self.Z = None self.ts = None - self.probFilterFlags = [] + self.ts_pre = None self.incpkgs = {} self.excpkgs = {} + self.pre_pkgs = [] + self.probFilterFlags = [ rpm.RPMPROB_FILTER_OLDPACKAGE, + rpm.RPMPROB_FILTER_REPLACEPKG ] self.has_prov_query = True @@ -85,6 +88,10 @@ class Zypp(BackendPlugin): self.ts.closeDB() self.ts = None + if self.ts_pre: + self.ts_pre.closeDB() + self.ts = None + self.closeRpmDB() if not os.path.exists("/etc/fedora-release") and \ @@ -370,6 +377,9 @@ class Zypp(BackendPlugin): def installHasFile(self, file): return False + def preInstall(self, pkg): + self.pre_pkgs.append(pkg) + def runInstall(self, checksize = 0): os.environ["HOME"] = "/" self.buildTransaction() @@ -636,6 +646,34 @@ class Zypp(BackendPlugin): self.close() raise + def preinstallPkgs(self): + if not self.ts_pre: + self.__initialize_transaction() + + self.ts_pre.order() + cb = rpmmisc.RPMInstallCallback(self.ts_pre) + cb.headmsg = "Preinstall" + installlogfile = "%s/__catched_stderr.buf" % (self.instroot) + + # start to catch stderr output from librpm + msger.enable_logstderr(installlogfile) + + errors = self.ts_pre.run(cb.callback, '') + # stop catch + msger.disable_logstderr() + self.ts_pre.closeDB() + self.ts_pre = None + + if errors is not None: + if len(errors) == 0: + msger.warning('scriptlet or other non-fatal errors occurred ' + 'during transaction.') + + else: + for e in errors: + msger.warning(e[0]) + raise RepoError('Could not run transaction.') + def installPkgs(self, package_objects): if not self.ts: self.__initialize_transaction() @@ -645,6 +683,7 @@ class Zypp(BackendPlugin): for flag in self.probFilterFlags: probfilter |= flag self.ts.setProbFilter(probfilter) + self.ts_pre.setProbFilter(probfilter) localpkgs = self.localpkgs.keys() @@ -670,10 +709,18 @@ class Zypp(BackendPlugin): raise RpmError("Error: %s doesn't exist" % rpmpath) h = rpmmisc.readRpmHeader(self.ts, rpmpath) + + if pkgname in self.pre_pkgs: + msger.verbose("pre-install package added: %s" % pkgname) + self.ts_pre.addInstall(h, rpmpath, 'u') + self.ts.addInstall(h, rpmpath, 'u') unresolved_dependencies = self.ts.check() if not unresolved_dependencies: + if self.pre_pkgs: + self.preinstallPkgs() + self.ts.order() cb = rpmmisc.RPMInstallCallback(self.ts) installlogfile = "%s/__catched_stderr.buf" % (self.instroot) @@ -725,6 +772,13 @@ class Zypp(BackendPlugin): # Set to not verify DSA signatures. self.ts.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS) + if not self.ts_pre: + self.ts_pre = rpm.TransactionSet(self.instroot) + # Just unpack the files, don't run scripts + self.ts_pre.setFlags(rpm.RPMTRANS_FLAG_ALLFILES | rpm.RPMTRANS_FLAG_NOSCRIPTS) + # Set to not verify DSA signatures. + self.ts_pre.setVSFlags(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS) + def checkPkg(self, pkg): ret = 1 if not os.path.exists(pkg): -- 2.7.4