diff --git a/pym/cl_fill_builder.py b/pym/cl_fill_builder.py index 1d4e418..16636d7 100644 --- a/pym/cl_fill_builder.py +++ b/pym/cl_fill_builder.py @@ -105,3 +105,33 @@ class fillVars(object, glob_attr): def get_cl_kernel_boot_path(self): return path.join(self.Get('cl_kernel_install_path'),"boot") + + def get_cl_kernel_cache_path(self): + cacheDir = self.getValueFromConfig('/etc/genkernel.conf','CACHE_DIR') + if cacheDir == False: + return "/var/cache/genkernel" + else: + return cacheDir + + def isChroot(self,pid): + """Recursive detect chroot mode""" + if not os.access('/proc/%d/environ'%pid,R_OK): + return False + if filter(lambda x:x=="_=/bin/chroot", + open('/proc/%d/environ'%pid,'r').read().split('\x00')): + return True + else: + ppid = filter(lambda x:x.startswith('PPid:'), + open('/proc/%d/status'%pid,'r').readlines())[0] + ppid = int(ppid.strip().partition('\t')[2]) + if ppid == 0: + return False + else: + return self.isChroot(ppid) + + def get_cl_chroot_status(self): + """Detect chroot mode by mtab content""" + try: + return "on" if self.isChroot(os.getpid()) else "off" + except: + return "off" diff --git a/pym/cl_kernel.py b/pym/cl_kernel.py index a84eb8b..73306db 100644 --- a/pym/cl_kernel.py +++ b/pym/cl_kernel.py @@ -48,6 +48,7 @@ class DataVarsBuilder(DataVars): class cl_kernel(color_print): """Primary class for kernel manipulation""" + kernelCurPath = '/usr/src/linux' def __init__(self): self.clVars = None @@ -74,12 +75,13 @@ class cl_kernel(color_print): self.clVars.flIniFile() def makeKernel(self,quiet=True,showMenuConfig=False,noClean=False, - lvmOpt=False,dmraidOpt=False,mdadmOpt=False): + lvmOpt=False,dmraidOpt=False,mdadmOpt=False, + mrproper=False): """Run kernel compilation""" clVars = self.clVars - standardParams = [ "--splash=tty1", "--unionfs", - "--all-ramdisk-modules","--disklabel", - "--slowusb", "--no-save-config"] + standardParams = ["--splash=tty1", "--unionfs", + "--all-ramdisk-modules","--disklabel", + "--slowusb", "--no-save-config"] kernelDir = ["--kerneldir=%s"%clVars.Get('cl_kernel_src_path')] kernelDestination = clVars.Get('cl_kernel_install_path') modulePrefix = ["--module-prefix=%s"%kernelDestination] @@ -103,15 +105,19 @@ class cl_kernel(color_print): lvmOpt = ["--lvm"] if lvmOpt else [] dmraidOpt = ["--dmraid"] if dmraidOpt else [] mdadmOpt = ["--mdadm"] if mdadmOpt else [] + mrproperOpt = ["--mrproper"] if mrproper else [] kernelName = ["--kernname=%s"%clVars.Get('os_linux_system')] + cachedir = ["--cachedir=%s"%clVars.Get('cl_kernel_cache_path')] + tempdir = ["--tempdir=%s"%clVars.Get('cl_kernel_temp_path')] - params = ["genkernel"]+standardParams+kernelDir+modulePrefix+\ + params = ["genkernel"]+cachedir+tempdir+\ + standardParams+kernelDir+modulePrefix+\ logLevel+makeOpts+menuConfig+noClean+kernelConfig+\ - bootDir+lvmOpt+dmraidOpt+mdadmOpt+["all"] + bootDir+lvmOpt+dmraidOpt+mdadmOpt+mrproperOpt+["all"] try: genkernelProcess = process(*params,stdout=None,stderr=STDOUT, - stdin=None) + stdin=None,envdict=os.environ) return genkernelProcess.success() except KeyboardInterrupt: self.printERROR("Keyboard interrupt") @@ -122,8 +128,7 @@ class cl_kernel(color_print): clVars = self.clVars bootDir = clVars.Get('cl_kernel_boot_path') if not os.access(bootDir,os.W_OK): - self.printERROR("No permissions to write to '%s'"% - bootDir) + self.printERROR(_("No permissions to write to '%s'")% bootDir) return False march = clVars.Get('os_arch_machine') if re.match("^i.86$",march): @@ -225,9 +230,9 @@ class cl_kernel(color_print): newConfigName = path.join(bootDir,"config-%s"%newSuffixName) kernelUid = clVars.Get('cl_kernel_uid') - symlinkInitrdName = path.join(bootDir,"initramfs-%s"%kernelUid) + symlinkInitrdName = path.join(bootDir,"initrd-%s"%kernelUid) symlinkInitrdNameInstall = path.join(bootDir, - "initramfs-%s-install"%kernelUid) + "initrd-%s-install"%kernelUid) symlinkKernelName = path.join(bootDir,"vmlinuz-%s"%kernelUid) symlinkSystemMap = path.join(bootDir,"System.map-%s"%kernelUid) try: @@ -237,18 +242,86 @@ class cl_kernel(color_print): self._installFile(systemMap,newSystemMap) self._installFile(configName,newConfigName) - self._installFile(newInitrdName,symlinkInitrdName, symlink=True) - self._installFile(newInitrdNameInstall,symlinkInitrdNameInstall, - symlink=True) - self._installFile(newKernelName,symlinkKernelName, symlink=True) - self._installFile(newSystemMap, symlinkSystemMap, symlink=True) + if not self.skipByChrootAndShortname(): + self._installFile(newInitrdName,symlinkInitrdName, symlink=True) + self._installFile(newInitrdNameInstall,symlinkInitrdNameInstall, + symlink=True) + self._installFile(newKernelName,symlinkKernelName, symlink=True) + self._installFile(newSystemMap, symlinkSystemMap, symlink=True) except (OSError,IOError),e: self.printERROR(_("Can not install kernel files: %s")%e.strerror) return False return True + def skipByChrootAndShortname(self): + """Return true if run from chroot or system not Calculate""" + clVars = self.clVars + return clVars.Get('cl_chroot_status') == 'on' or \ + clVars.Get('os_linux_shortname') in ('Gentoo','Linux') + + def versionMigrate(self): + clVars = self.clVars + if self.skipByChrootAndShortname(): + return True + calculate2env = clVars.Get('cl_env_path')[0] + if not path.exists(calculate2env) or \ + not filter(lambda x:x.startswith('cl_kernel_uid'), + open(calculate2env,'r')): + return self.performVersionMigrate() + return True + + def performVersionMigrate(self): + """Generate cl_kernel_uid, write to calculate2.env, fix grub.conf""" + clVars = self.clVars + clKernelUid = clVars.Get('cl_kernel_uid') + clVars.Write('cl_kernel_uid',clKernelUid,force=True) + reChangeKernel = \ + re.compile("(/boot/(?:vmlinuz))(?:-\S+?)?((?:-install)?) ") + reChangeInitrd = \ + re.compile("(/boot/)(?:initrd|initramfs)(?:-\S+?)?((?:-install)?)$") + grubconf = '/boot/grub/grub.conf' + rootdev = clVars.Get('os_root_dev') + def grubreduce(x,y): + if y.startswith('title'): + x[0] = False + elif y.startswith('kernel') and "root=%s"%rootdev in y: + x[0] = True + if x[0]: + y = reChangeKernel.sub("\\1-%s\\2 "%clKernelUid,y) + y = reChangeInitrd.sub("\\1initrd-%s\\2"%clKernelUid,y) + return [x[0],x[1] + [y]] + + if not os.access(grubconf,os.W_OK): + self.printERROR(_("No permissions to write to '%s'")%grubconf) + return False + newGrub = reduce(grubreduce,open(grubconf,'r'),[False,[]])[1] + open(grubconf,'w').writelines(newGrub) + return True + + def setKernelForCurrent(self): + """Set compiled kernel to current""" + clVars = self.clVars + if self.skipByChrootAndShortname(): + return True + # compiling kernel not current. + clKernelPath = clVars.Get('cl_kernel_src_path') + if not clKernelPath in (self.kernelCurPath, + path.realpath(self.kernelCurPath)) and \ + path.islink(self.kernelCurPath): + os.unlink(self.kernelCurPath) + kernelName = path.basename(path.normpath(clKernelPath)) + try: + os.symlink(kernelName,self.kernelCurPath) + except (IOError,OSError),e: + self.printERROR(str(e)) + return False + return True + def cleanInitrd(self): + """Discard from initrd non-critical modules""" clVars = self.clVars + if self.skipByChrootAndShortname(): + return True bootDir = clVars.Get('cl_kernel_boot_path') clKernelUid = clVars.Get('cl_kernel_uid') initrdName = path.join(bootDir,"initramfs-%s-install"%clKernelUid) diff --git a/pym/cl_kernel_cmd.py b/pym/cl_kernel_cmd.py index 5b67eee..ee70bc2 100644 --- a/pym/cl_kernel_cmd.py +++ b/pym/cl_kernel_cmd.py @@ -17,6 +17,7 @@ from cl_kernel import cl_kernel, __app__, __version__ from cl_opt import opt from cl_share_cmd import share_cmd +import os from os import path from os import access,R_OK import re @@ -54,6 +55,9 @@ CMD_OPTIONS = [{'shortOption':"c", 'longOption':"menuconfig", 'help':_("run menuconfig after oldconfig") }, + {'longOption':"mrproper", + 'help':_("run make mrproper before compilation") + }, {'longOption':"no-clean", 'help':_("do not run make clean before compilation") }, @@ -65,7 +69,9 @@ CMD_OPTIONS = [{'shortOption':"c", 'help':_("do not display kernel compilation process") }, {'longOption':"initrd", - 'help':_("perform current initramfs optimization")} + 'help':_("perform current initramfs optimization")}, + {'longOption':"ebuild", + 'help':_("build kernel by ebuild phase (need ebuild enviroment)")} ] @@ -103,10 +109,21 @@ class kernel_cmd(share_cmd): self.optobj.error(_("incompatible options")+":"+" %s"\ %self.getStringIncompatibleOptions(incompatible+["initrd"])) + def checkEnviromentForEbuild(self): + """Check current enviroment for ebuild enviroment variables""" + missedEnvVar = filter(lambda x:not x in os.environ, + ['S','T','D','ROOT','WORKDIR', + 'EBUILD_PHASE']) + if missedEnvVar: + self.optobj.error(_("Can not read some ebuild variable: %s")% + ", ".join(missedEnvVar)) + def checkOpts(self, values, args): """Check values all specified options.""" if len(args) > 0: self.optobj.error(_("unrecognized option") + ": %s"% "".join(args)) + if values.ebuild: + self.checkEnviromentForEbuild() if values.initrd: self.checkIncompatibleInitrd() if values.k: @@ -129,11 +146,9 @@ class kernel_cmd(share_cmd): configFile = values.c self.logicObj.clVars.Set('cl_kernel_config',configFile,True) elif values.o: - if not path.exists( + if path.exists( path.join(self.logicObj.clVars.Get('cl_kernel_src_path'), ".config")): - self.optobj.error(_("kernel directory has not config")) - else: self.logicObj.clVars.Set('cl_kernel_config', path.join(self.logicObj.clVars.Get('cl_kernel_src_path'), ".config.bak"),True) @@ -149,20 +164,35 @@ class kernel_cmd(share_cmd): self.printSUCCESS(_("Initramfs successfully optimized")) return True + def checkEbuildParam(self,options,phase): + return not options.ebuild or os.environ["EBUILD_PHASE"] == phase + def makeKernel(self,options): - if not self.logicObj.makeKernel(quiet=options.q, + """Run kernel compilation, installation, optimization""" + # if set ebuild param check cur EBUILD_PHASE, run kernel compilation + if self.checkEbuildParam(options,"compile"): + if not self.logicObj.makeKernel(quiet=options.q, showMenuConfig=options.m, noClean=options.no_clean, lvmOpt=options.lvm, dmraidOpt=options.dmraid, - mdadmOpt=options.mdadm): - self.printERROR(_("Failed kernel compilation")) - return False - if not self.logicObj.prepareBoot(): - self.printERROR(_("Failed prepare boot directory")) - return False - if not self.logicObj.installBootFiles(): - self.printERROR(_("Failed install kernel")) - return False + mdadmOpt=options.mdadm, + mrproper=options.mrproper): + self.printERROR(_("Failed kernel compilation")) + return False + if not self.logicObj.prepareBoot(): + self.printERROR(_("Failed prepare boot directory")) + return False + if self.checkEbuildParam(options,"postinst"): + if not self.logicObj.installBootFiles(): + self.printERROR(_("Failed kernel install")) + return False + if not self.logicObj.versionMigrate(): + self.printERROR(_("Failed kernel nomenclature update")) + return False + if not self.logicObj.cleanInitrd(): + self.printWARNING(_("Failed initramfs optimization")) + if not self.logicObj.setKernelForCurrent(): + self.printWARNING(_("Failed change '%s'")%"/usr/scr/linux") return True diff --git a/pym/cl_vars_builder.py b/pym/cl_vars_builder.py index 9876e9e..348c0af 100644 --- a/pym/cl_vars_builder.py +++ b/pym/cl_vars_builder.py @@ -55,3 +55,12 @@ class Data: # root path for kernel installation (value+lib/modules) cl_kernel_install_path = {'mode':'w','value':'/'} + + # override location of Calckernel's temporary directory + cl_kernel_temp_path = {'mode':'w','value':'/var/calculate/tmp/genkernel'} + + # override the default cache location for calckernel + cl_kernel_cache_path = {'mode':'w'} + + # is shell in chroot + cl_chroot_status = {}