You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-2.2-builder/pym/cl_kernel.py

498 lines
21 KiB

#-*- coding: utf-8 -*-
# Copyright 2010 Calculate Ltd. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import re
import sys
import traceback
from os import path
from cl_builder import DataVarsBuilder, printNoColor, __version__, __app__
from cl_utils import process,listDirectory,cmpVersion,reVerSplitToPV, \
reVerSplit,getPkgInstalled,PIPE,STDOUT
from cl_vars_share import varsShare
from subprocess import STDOUT,PIPE
from cl_print import color_print
from shutil import copy2 as copy_with_perm
from cl_kernel_utils import KernelConfig,InitRamFs
from cl_lang import lang
lang().setLanguage(sys.modules[__name__])
class changer:
"""Reducer for change block by condition
def up(self,y) - condition to start change
def drop(self,y) - condition to stop change
def change(self,y) - perform string change.
Using:
class changer:
up = lambda self,y: "test" in y
drop = lambda self,y: "stop" in y
change = lambda self,y: y.replace("abc","zxc")
listing = changer().reduce(listing)
"""
initReduce = [False,[]]
def __call__(self,x,y):
if self.drop(y):
x[0] = False
if self.up(y):
x[0] = True
if x[0]:
y = self.change(y)
return [x[0],x[1] + [y]]
def reduce(self,obj):
"""Perform reduce"""
return reduce(self,obj,self.initReduce)[1]
class cl_kernel(color_print):
"""Primary class for kernel manipulation"""
kernelCurPath = '/usr/src/linux'
def __init__(self):
self.clVars = None
self.startMessage = ""
def _testKernelDirectory(self,dirpath):
"""Test directory for kernel sources"""
makefilepath = path.join(dirpath,'Makefile')
kbuildpath = path.join(dirpath,'Kbuild')
if path.exists(makefilepath) \
and path.exists(kbuildpath) \
and "Kbuild for top-level directory of the kernel" in \
open(kbuildpath,'r').read():
return True
return False
def _testFullKernelDirectory(self,dirpath):
"""To check the directory for full kernel sources
Kernel may be installed with minimal (later vmlinuz) flag"""
documentationPath = path.join(dirpath,'Documentation')
driversPath = path.join(dirpath,'drivers')
if path.exists(documentationPath) \
and path.exists(driversPath):
return True
return False
def setNoColor(self):
self.color = False
def initVars(self):
"""Primary initialization of variables"""
self.clVars = DataVarsBuilder()
self.clVars.importBuilder()
self.clVars.flIniFile()
def makeKernel(self,quiet=True,showMenuConfig=False,noClean=False,
lvmOpt=False,dmraidOpt=False,mdadmOpt=False,
mrproper=False,target="all"):
"""Run kernel compilation"""
clVars = self.clVars
themeName = "calculate"
standardParams = ["--splash=%s"%themeName, "--unionfs",
"--all-ramdisk-modules","--disklabel",
"--no-save-config", "--firmware","--udev",
"--lspci","--logfile=%s"%
path.join(clVars.Get('cl_kernel_src_path'),
"genkernel.log")]
kernelDir = ["--kerneldir=%s"%clVars.Get('cl_kernel_src_path')]
kernelDestination = clVars.Get('cl_kernel_install_path')
modulePrefix = ["--module-prefix=%s"%kernelDestination]
if not path.exists(kernelDestination):
self.printERROR("Not found destination directory '%s'"%
kernelDestination)
return False
logLevel = ["--loglevel=%d"%(1 if quiet else 2)]
makeOpts = clVars.Get('os_builder_makeopts')
if makeOpts:
makeOpts = ["--makeopts=%s"%makeOpts]
else:
makeOpts = []
menuConfig = ["--menuconfig"] if showMenuConfig else []
noClean = ["--no-clean"] if noClean else []
bootDir = clVars.Get('cl_kernel_boot_path')
if not path.exists(bootDir):
os.makedirs(bootDir,mode=0755)
bootDir = ["--bootdir=%s"%bootDir]
lvmOpt = ["--lvm"] if lvmOpt else []
dmraidOpt = ["--dmraid"] if dmraidOpt else []
mdadmOpt = ["--mdadm"] if mdadmOpt else []
mrproperOpt = ["--mrproper"] if mrproper else ["--no-mrproper"]
stdConfigPath = \
path.join(clVars.Get('cl_kernel_src_path'), ".config")
if clVars.Get('cl_kernel_config') == stdConfigPath:
kernelConfig = []
if mrproper:
self.printERROR(_("Cannot use the current kernel configuration"
" with option'%s'")%
"--mrproper")
return False
else:
kernelConfig = ["--kernel-config=%s"%clVars.Get('cl_kernel_config')]
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"]+cachedir+tempdir+\
standardParams+kernelDir+modulePrefix+\
logLevel+makeOpts+menuConfig+noClean+kernelConfig+\
bootDir+lvmOpt+dmraidOpt+mdadmOpt+mrproperOpt+[target]
try:
genkernelProcess = process(*params,stdout=None,stderr=STDOUT,
stdin=None,envdict=os.environ)
return genkernelProcess.success()
except KeyboardInterrupt:
self.printERROR("Keyboard interrupt")
return False
def prepareBoot(self):
"""Rename received by genkernel files"""
clVars = self.clVars
bootDir = clVars.Get('cl_kernel_boot_path')
if not os.access(bootDir,os.W_OK):
self.printERROR(_("No permission to write to '%s'")% bootDir)
return False
march = clVars.Get('os_arch_machine')
if re.match("^i.86$",march):
march = "x86"
baseConfigName = path.join(clVars.Get('cl_kernel_src_path'),
".config")
if path.exists(baseConfigName):
clVars.Set('cl_kernel_config',baseConfigName,True)
kernelFullVer = clVars.Get('cl_kernel_full_ver')
suffixName = "genkernel-%(march)s-%(fullver)s"%\
{"march":march,
"fullver":kernelFullVer}
baseInitrdName = path.join(bootDir,"initramfs-%s"%suffixName)
baseKernelName = path.join(bootDir,"kernel-%s"%suffixName)
baseSystemMap = path.join(bootDir,"System.map-%s"%suffixName)
newInitrdName = self._getName("initramfs")
newKernelName = self._getName("vmlinuz")
newSystemMap = self._getName("System.map")
newConfigName = self._getName("config")
try:
os.rename(baseInitrdName,newInitrdName)
os.rename(baseKernelName,newKernelName)
os.rename(baseSystemMap,newSystemMap)
copy_with_perm(baseConfigName,newConfigName)
except OSError,e:
self.printERROR(_("Failed to rename kernel files: %s")%e.strerror)
return False
return True
def _installFile(self,source,target,removeSource=True,symlink=False):
"""Copy, move or create symlink source file to target. Save old."""
def getLinkForTarget(target):
"""Get symlinks from target dirname which point to target"""
baseDir = path.dirname(path.normpath(target))
linkFiles = filter(path.islink,map(lambda x:path.join(baseDir,x),
os.listdir(baseDir)))
return filter(lambda x:path.join(baseDir,
os.readlink(x))==target, linkFiles)
# raise IOError if source is not exists
open(source,'r').close()
targetLinkFiles = getLinkForTarget(target)
oldtarget = ""
if path.lexists(target):
oldtarget = "%s.old" % target
if path.lexists(oldtarget):
oldTargetLinkFiles = getLinkForTarget(oldtarget)
map(os.unlink,oldTargetLinkFiles)
os.unlink(oldtarget)
os.rename(target,oldtarget)
if symlink:
if path.dirname(source)==path.dirname(target):
os.symlink(path.basename(source),target)
else:
os.symlink(source,target)
elif removeSource:
os.rename(source,target)
else:
copy_with_perm(source,target)
if oldtarget:
map(os.unlink,targetLinkFiles)
map(lambda x:os.symlink(path.basename(oldtarget),x),targetLinkFiles)
def _getName(self,obj):
"""Get names for (initramfs,initramfs-install,vmlinuz,System.map,
config) after kernel compilation (installed)"""
clVars = self.clVars
bootDir = clVars.Get('cl_kernel_boot_path')
kernelFullVer = clVars.Get('cl_kernel_full_ver')
fullVerWithoutCalculate = kernelFullVer.replace("-calculate","")
suffixName = "%s-%s-%s-installed"%(fullVerWithoutCalculate,
clVars.Get('os_arch_machine'),
clVars.Get('os_linux_shortname'))
if obj == "config-kernelver":
suffixName = kernelFullVer
obj = "config"
return path.join(bootDir,{"initramfs":"initramfs-%s",
"initramfs-install":"initramfs-%s",
"vmlinuz":"vmlinuz-%s",
"System.map":"System.map-%s",
"config":"config-%s"}[obj]%suffixName)
def _getNewName(self,obj):
"""Get new names for (initramfs,initramfs-install,vmlinuz,System.map,
config) which they have after renaming"""
clVars = self.clVars
bootDir = clVars.Get('cl_kernel_boot_path')
kernelFullVer = clVars.Get('cl_kernel_full_ver')
fullVerWithoutCalculate = kernelFullVer.replace("-calculate","")
newSuffixName = "%s-%s-%s"%(fullVerWithoutCalculate,
clVars.Get('os_arch_machine'),
clVars.Get('os_linux_shortname'))
return path.join(bootDir,{"initramfs":"initramfs-%s",
"initramfs-install":"initramfs-%s-install",
"vmlinuz":"vmlinuz-%s",
"System.map":"System.map-%s",
"config":"config-%s"}[obj]%newSuffixName)
def _getSymlink(self,obj):
"""Get uid symlinks (initramfs,initramfs-install,vmlinuz,System.map)
they pointet to object by _getNewName"""
clVars = self.clVars
bootDir = clVars.Get('cl_kernel_boot_path')
kernelUid = clVars.Get('cl_kernel_uid')
return path.join(bootDir,{"initramfs":"initrd-%s",
"initramfs-install":"initrd-%s-install",
"vmlinuz":"vmlinuz-%s",
"System.map":"System.map-%s"}[obj]%kernelUid)
def installBootFiles(self):
"""Copy -install files to without suffix name, and save old copy.
initramfs, vmlinuz, System.map, config with suffix installed copy
withou suffix. Save old files by append suffix .old.
Search link files boot directory link to oldfiles and fix symlink.
Create initramfs install (copy of initramfs)
"""
initrdName = self._getName("initramfs")
kernelName = self._getName("vmlinuz")
systemMap = self._getName("System.map")
configName = self._getName("config")
newInitrdName = self._getNewName("initramfs")
newInitrdNameInstall = self._getNewName("initramfs-install")
newKernelName = self._getNewName("vmlinuz")
newSystemMap = self._getNewName("System.map")
newConfigName = self._getNewName("config")
symlinkConfigKernelName = self._getName("config-kernelver")
try:
self._installFile(initrdName,newInitrdName,removeSource=False)
self._installFile(initrdName,newInitrdNameInstall)
self._installFile(kernelName,newKernelName)
self._installFile(systemMap,newSystemMap)
self._installFile(configName,newConfigName)
self._installFile(newConfigName,symlinkConfigKernelName,
removeSource=False,symlink=True)
except (OSError,IOError),e:
self.printERROR(_("Failed to 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]
return self.performVersionMigrate()
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)
grubconf = '/boot/grub/grub.conf'
grub2conf = '/boot/grub/grub.cfg'
rootdev = clVars.Get('os_root_dev')
x11video = clVars.Get('os_x11_video_drv')
class grubsetUID(changer):
reChangeKernel = \
re.compile("(/boot/(?:vmlinuz))(?:-\S+?)?((?:-install)?) ")
reChangeInitrd = \
re.compile("(/boot/)(?:initrd|initramfs)"
"(?:-\S+?)?((?:-install)?)$")
drop = lambda self,y: y.startswith('title')
up = lambda self,y: y.startswith('kernel') and \
"root=%s"%rootdev in y
def change(self,y):
y = self.reChangeKernel.sub("\\1-%s\\2 "%clKernelUid,y)
return self.reChangeInitrd.sub("\\1initrd-%s\\2"%clKernelUid,y)
class grubchangeCONSOLE(grubsetUID):
up = lambda self,y: y.startswith('kernel') and \
"/boot/vmlinuz-%s"%clKernelUid in y
change = lambda self,y: y.replace('CONSOLE=/dev/','console=')
class grubchangeVideo(grubchangeCONSOLE):
reChangeCalculate = re.compile(r'(?: calculate=\S+|$)')
drop = lambda self,y: not y.startswith('kernel')
change = lambda self,y:self.reChangeCalculate.sub(
' calculate=video:%s'%x11video,y,1)
# if has grub2
if filter(lambda x:x.startswith("grub-1.99") or \
x.startswith("grub-2"),
listDirectory('/var/db/pkg/sys-boot')):
grubInstall = process('/usr/sbin/cl-core','--method','core_setup',
'--pkg-name','grub',
'--no-progress',stderr=None)
grubInstall.success()
if not filter(lambda x:x.startswith("grub-0.9"),
listDirectory('/var/db/pkg/sys-boot')) or not path.exists(grubconf):
return True
if not os.access(grubconf,os.W_OK):
self.printERROR(_("No permission to write to '%s'")%grubconf)
return False
calcKernel = filter(lambda x:x['PN'] == 'calckernel',
map(reVerSplitToPV,
filter(lambda x:x,
map(lambda x:reVerSplit.search(x),
listDirectory('/var/db/pkg/sys-kernel')))))
newGrub = grubsetUID().reduce(open(grubconf,'r'))
if calcKernel and cmpVersion(calcKernel[-1]['PVR'],"3.4.14") >= 0:
newGrub = grubchangeCONSOLE().reduce(newGrub)
newGrub = grubchangeVideo().reduce(newGrub)
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 checkConflictOptions(self):
"""Clean initrd from needless modules"""
# section which must contains equealent modules and kernel buildins
importantSections = ['File systems','Pseudo filesystems',
'CDROM.*Filesystems', 'DOS.*Filesystems',
'SCSI Transport']
# get dictionary from current config
curConfig = dict(KernelConfig().getSectionParams(*importantSections))
# get config of new kernel
newConfig = KernelConfig(configFile=self._getNewName("config"))
newConfig = newConfig.getSectionParams(*importantSections)
# find and return conflict option
# options, which M in new config and Y in current config
return filter(lambda x: x[1]=="M" and
x[0] in curConfig and
curConfig[x[0]]=="Y",
newConfig)
def createInitrd(self,lvmOpt=False, dmraidOpt=False, mdadmOpt=False):
"""Recreate initrd"""
if self.makeKernel(quiet=True,
showMenuConfig=False,noClean=False,
lvmOpt=lvmOpt,dmraidOpt=dmraidOpt,mdadmOpt=mdadmOpt,
mrproper=False,target="ramdisk"):
clVars = self.clVars
bootDir = clVars.Get('cl_kernel_boot_path')
if not os.access(bootDir,os.W_OK):
self.printERROR(_("No permission to write to '%s'")% bootDir)
return False
march = clVars.Get('os_arch_machine')
if re.match("^i.86$",march):
march = "x86"
kernelFullVer = clVars.Get('cl_kernel_full_ver')
suffixName = "genkernel-%(march)s-%(fullver)s"%\
{"march":march,
"fullver":kernelFullVer}
baseInitrdName = path.join(bootDir,"initramfs-%s"%suffixName)
newInitrdName = self._getNewName("initramfs")
try:
os.rename(baseInitrdName,newInitrdName)
except OSError,e:
self.printERROR(_("Failed to rename initramfs files: %s")
%e.strerror)
return False
return True
return False
def cleanInitrd(self):
"""Discard from initrd non-critical modules"""
clVars = self.clVars
if self.skipByChrootAndShortname():
return True
# check conflict options
#if self.checkConflictOptions():
# return True
bootDir = clVars.Get('cl_kernel_boot_path')
clKernelUid = clVars.Get('cl_kernel_uid')
initrdName = path.join(bootDir,"initramfs-%s-install"%clKernelUid)
optInitrdName = path.join(bootDir,"initramfs-%s"%clKernelUid)
# old mode (for compatibility)
if not path.lexists(initrdName) or not path.lexists(optInitrdName):
kernelFullVer = clVars.Get('cl_kernel_full_ver')
fullVerWithoutCalculate = kernelFullVer.replace("-calculate","")
suffixName = "%s-%s-%s"%(fullVerWithoutCalculate,
clVars.Get('os_arch_machine'),
clVars.Get('os_linux_shortname'))
initrdName = path.join(bootDir,"initramfs-%s-install"%suffixName)
optInitrdName = path.join(bootDir,"initramfs-%s"%suffixName)
if path.exists(path.realpath(optInitrdName)):
os.unlink(path.realpath(optInitrdName))
try:
initRamFs = InitRamFs(initrdName)
hr_video = {'nvidia':'nouveau',
'ati':'radeon',
'intel':'intel'}.get(clVars.Get('hr_video'),"")
x11_video_drv = self.clVars.Get('os_x11_video_drv')
if x11_video_drv == hr_video:
x11_video_drv = ""
return initRamFs.cleanInitRamFs(path.realpath(optInitrdName),
x11_video_drv)
except (OSError,IOError),e:
self.printERROR(str(e))
return False