#-*- 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. __version__ = "2.2.26" __app__ = "calculate-install" import os import re import sys import traceback from os import path from cl_utils import runOsCommand,appendProgramToEnvFile, \ removeProgramToEnvFile,pathJoin, \ scanDirectory,process,getTupleVersion, \ detectDeviceForPartition,listDirectory, \ cmpVersion,STDOUT,getUdevDeviceInfo, \ getLvmPartitions,getInstalledVideo, \ getSupportArch, refreshLVM, refreshUdev, \ isPkgInstalled from cl_vars_share import varsShare from cl_kernel_utils import KernelConfig,InitRamFs import cl_overriding from StringIO import StringIO from utils import ip install_errors = "" def installExit(*args,**kwars): raise InstallError(globals()["install_errors"]) def overprintERROR(s): globals()["install_errors"] += str(s) +"\n" def get_install_errors(): return globals()["install_errors"] def pop_install_errors(): res = globals()["install_errors"] globals()["install_errors"] = "" return res defaultExit = cl_overriding.exit defaultPrintERROR = cl_overriding.printERROR from cl_lang import lang from cl_fill import clLocale from cl_template import template from cl_datavars import DataVars from cl_print import color_print from cl_distr import PartitionDistributive,DistributiveRepository,\ DistributiveError, ScratchPartitionDistributive, \ MultiPartitions, Spinner, FlashDistributive, SignalInterrupt,\ Distributive, PxeDistributive from cl_string import tableReport from time import sleep from subprocess import PIPE,STDOUT from server.utils import dialogYesNo from cl_migrate_users import migrate, currentUsers from cl_utils import getUserPassword from encrypt import encrypt from shutil import copy2 from cl_lang import lang lang().setLanguage(sys.modules[__name__]) class InstallError(Exception): """Installation Error""" pass class printNoColor: def colorPrint(self,attr,fg,bg,string): sys.stdout.write(string) class DataVarsInstall(DataVars): """Variable class for installation""" def importInstall(self, **args): '''Заполнить конфигурацию переменных, для десктопа''' # Имя секции в calculate.env envSection = "install" # заполнить переменные окружения алгоритмом по умолнанию self.importData(envSection, ('cl_vars_install','cl_fill_install')) class convertDictOpt: """Convert dict install option""" _defaultFS = "ext4" _defaultFlashFS = "vfat" _diskDefaultMountPoints = { "default":{"fileSystem":_defaultFS, "isFormat":False, "options":["noatime"]}, "/":{"fileSystem":_defaultFS, "isFormat":True, "options":["noatime"]}, "none":{"fileSystem":"", "isFormat":False, "options":[""]},} #"/boot":{"fileSystem":"ext2", # "isFormat":True, # "options":["noatime"]}} _bindDefaultMountPoint = {"fileSystem":"none", "isFormat":False, "options":["bind"]} _swapDefaultMountPoint = {"fileSystem":"swap", "isFormat":False, "options":["sw"]} _propertiesFileSystem = {"default": {"fileSystem":_defaultFS, "isFormat":True, "options":["noatime"]}, "noformat":{"fileSystem":"", "isFormat":False, "options":["noatime"]}, "defaultflash":{"fileSystem":_defaultFlashFS, "isFormat":True, "options":["noatime"]}} _ext2Options = {"options":["acl", "noacl", "bsddf", "minixdf", "check", "debug", "errors", "grpid", "bsdgroups", "nogrpid", "sysvgroups", "grpquota", "noquota", "quota", "usrquota","nobh", "nouid32", "oldalloc", "orlov", "resgid","resuid", "sb", "user_xattr", "nouser_xattr"], "pair":{"check":{"options":["none", "nocheck"], "incompatible":["none", "nocheck"]}, "errors":{"options":["continue", "remount-ro", "panic"], "incompatible":["continue","remount-ro", "panic"]}, "resgid":{"options":re.compile("\d+"), "incompatible":[]}, "resuid":{"options":re.compile("\d+"), "incompatible":[]}, "sb":{"options":re.compile("\d+"), "incompatible":[]}}, "incompatible":[["acl","noacl"], ["bsddf", "minixdf"], ["grpid","bsdgroups"], ["grpid","nogrpid"], ["bsdgroups","sysvgroups"], ["nogrpid","sysvgroups"], ["grpquota","noquota","quota", "usrquota"], ["oldalloc","orlov"], ["user_xattr","nouser_xattr"]], "makefs":"/sbin/mkfs.ext2"} _ext3Options = _ext2Options.copy() _ext3Options.update({"makefs":"/sbin/mkfs.ext3"}) _ext3Options["options"] += ["journal", "noload", "data", "barrier", "commit", "data_err"] _ext3Options["pair"].update({"journal":{"options":["update", "inum"], "incompatible":["update", "inum"]}, "data":{"options":["journal", "ordered", "writeback"], "incompatible":["journal", "ordered", "writeback"]}, "data_err":{"options":["abort", "ordered", "ignore"], "incompatible":["abort", "ordered", "ignore"]}, "barrier":{"options":["0","1"], "incompatible":["0","1"]}, "commit":{"options":re.compile("\d+"), "incompatible":[]}}) _fileSystemOpt = {"_all":{"options":["async", "atime", "noatime", "auto", "noauto", "defaults", "dev", "nodev", "diratime", "nodiratime", "dirsync", "exec", "noexec", "group", "iversion", "noiversion", "mand", "nomand", "_netdev", "nofail", "relatime", "norelatime", "strictatime", "nostrictatime", "suid", "nosuid", "owner", "remount", "ro", "rw", "sync", "user", "nouser", "users"], "pair": {}, "incompatible":[["sync", "async"], ["atime", "noatime"], ["auto", "noauto"], ["dev", "nodev"], ["diratime", "nodiratime"], ["exec", "noexec"], ["iversion", "noiversion"], ["mand", "nomand"], ["relatime", "norelatime"], ["strictatime", "nostrictatime"], ["suid", "nosuid"], ["ro", "rw"], ["user", "nouser"]]}, "ext2":_ext2Options, "ext3":_ext3Options, "ext4":{"options":["journal_dev", "noload", "data", "commit", "orlov", "oldalloc", "user_xattr", "nouser_xattr", "acl", "noacl", "bsddf", "minixdf", "debug", "errors", "data_err", "grpid", "bsdgroups", "nogrpid", "sysvgroups", "resgid", "resuid", "sb", "quota", "noquota", "grpquota", "usrquota", "bh", "nobh", "journal_checksum", "journal_async_commit", "journal", "barrier", "nobarrier", "inode_readahead", "stripe", "delalloc", "nodelalloc", "max_batch_time", "journal_ioprio", "auto_da_alloc", "noauto_da_alloc"], "pair": {"journal_dev":{\ "options":re.compile(".+"), "incompatible":[]}, "data":{"options":["journal", "ordered", "writeback"], "incompatible":["journal", "ordered", "writeback"]}, "commit":{"options":re.compile("\d+"), "incompatible":[]}, "errors":{"options":["continue", "remount-ro", "panic"], "incompatible":["continue", "remount-ro", "panic"]}, "data_err":{"options":["abort", "ordered", "ignore"], "incompatible":["abort", "ordered", "ignore"]}, "resgid":{"options":re.compile("\d+"), "incompatible":[]}, "resuid":{"options":re.compile("\d+"), "incompatible":[]}, "sb":{"options":re.compile("\d+"), "incompatible":[]}, "journal":{"options":["update"], "incompatible":[]}, "inode_readahead":{"options":\ re.compile("\d+"), "incompatible":[]}, "stripe":{"options":re.compile("\d+"), "incompatible":[]}, "max_batch_time":{"options":\ re.compile("\d+"), "incompatible":[]}, "journal_ioprio":{"options":\ re.compile("[1-7]"), "incompatible":[]}}, "incompatible":[["oldalloc", "orlov"], ["user_xattr","nouser_xattr"], ["acl", "noacl"], ["bsddf", "minixdf"], ["grpid","bsdgroups"], ["grpid","nogrpid"], ["bsdgroups","sysvgroups"], ["nogrpid","sysvgroups"], ["grpquota","noquota","quota", "usrquota"], ["bh","nobh"], ["delalloc", "nodelalloc"], ["auto_da_alloc", "noauto_da_alloc"]], "makefs":"/sbin/mkfs.ext4"}, "reiserfs":{"options":["conv","hash","hashed_relocation", "no_unhashed_relocation", "noborder", "nolog", "notail", "replayonly", "resize", "user_xattr", "acl"], "pair":{"hash":{"options":["rupasov", "tea", "r5", "detect"], "incompatible":["rupasov", "tea", "r5", "detect"]}, "resize":{"options":re.compile("\d+"), "incompatible":[]}}, "incompatible":[], "makefs":"/sbin/mkfs.reiserfs"}, "vfat":{"options":["uni_xlate","posix","nonumtail", "utf8","shortname"], "pair":{"shortname":{"options": re.compile("lower|win95|winnt|mixed"), "incompatible":[]}, "utf8":{"options": re.compile("0|1|no|false|true|yes"), "incompatible":["uni_xlate"]}}, "incompatible":[], "makefs":"/usr/sbin/mkfs.vfat"}, "btrfs":{"options":[], "pair":{}, "incompatible":[], "makefs":"/sbin/mkfs.btrfs"}, "nilfs2":{"options":[], "pair":{}, "incompatible":[], "makefs":"/sbin/mkfs.nilfs2"}, "jfs":{"options":[], "pair":{}, "incompatible":[], "makefs":"/sbin/mkfs.jfs"}, "ntfs":{"options":["uni_xlate","posix","nls", "utf8","iocharset", "uid","gid","umask"], "pair":{"utf8":{"options": re.compile("0|1|no|false|true|yes"), "incompatible":["uni_xlate"]}, "iocharset":{"options":re.compile(".+"), "incompatible":["nls"]}, "uni_xlate":{"options": re.compile("0|1|2"), "incompatible":[]}, "posix":{"options": re.compile("0|1"), "incompatible":[]}, "uid":{"options":re.compile(".+"), "incompatible":[]}, "gid":{"options":re.compile(".+"), "incompatible":[]}, "umask":{"options":re.compile(".+"), "incompatible":[]}, }, "incompatible":[], "makefs":"/usr/sbin/mkfs.ntfs"}, "ntfs-3g":{"options":["uid","gid","umask","fmask", "dmask","usermapping", "default_permissions", "inherit","locale", "force","remove_hiberfile", "show_sys_files","allow_other", "max_read","silent","no_def_opts", "streams_interface","user_xattr", "efs_raw","debug","no_detach"], "pair":{"uid":{"options":re.compile(".+"), "incompatible":[]}, "gid":{"options":re.compile(".+"), "incompatible":[]}, "umask":{"options":re.compile(".+"), "incompatible":[]}, "fmask":{"options":re.compile(".+"), "incompatible":[]}, "dmask":{"options":re.compile(".+"), "incompatible":[]}, "usermapping":{"options":re.compile(".+"), "incompatible":[]}, "default_permissions":{ "options":re.compile(".+"), "incompatible":[]}, "locale":{"options":re.compile(".+"), "incompatible":[]}, "max_read":{"options":re.compile(".+"), "incompatible":[]}, "streams_interface":{ "options":re.compile(".+"), "incompatible":[]}}, "incompatible":[], "makefs":"/usr/sbin/mkfs.ntfs"}, "xfs":{"options":["allocsize", "attr2", "noattr2", "barrier", "dmapi", "grpid", "bsdgroups", "nogrpid", "sysvgroups", "ihashsize", "ikeep", "noikeep", "inode64", "largeio","nolargeio", "logbufs", "logbsize", "logdev", "rtdev", "mtpt", "noalign", "noatime", "norecovery", "nouuid", "osyncisosync", "uquota", "usrquota", "uqnoenforce", "quota", "pquota", "prjquota", "pqnoenforce", "sunit", "swidth", "swalloc"], "pair":{"allocsize":{"options":re.compile("\d+"), "incompatible":[]}, "ihashsize":{"options":re.compile("\d+"), "incompatible":[]}, "logbufs":{"options":re.compile("\d+"), "incompatible":[]}, "logbsize":{"options":re.compile("\d+"), "incompatible":[]}, "logdev":{"options":re.compile(".+"), "incompatible":[]}, "rtdev":{"options":re.compile(".+"), "incompatible":[]}, "mtpt":{"options":re.compile(".+"), "incompatible":[]}, "sunit":{"options":re.compile("\d+"), "incompatible":[]}, "swidth":{"options":re.compile("\d+"), "incompatible":[]}}, "incompatible":[["attr2", "noattr2"], ["grpid", "bsdgroups"], ["grpid", "nogrpid"], ["bsdgroups", "sysvgroups"], ["nogrpid", "sysvgroups"], ["ikeep", "noikeep"], ["largeio","nolargeio"], ["uquota", "usrquota", "uqnoenforce", "quota"], ["pquota", "prjquota", "pqnoenforce"]], "makefs":"/sbin/mkfs.xfs"}} listFileSystemCorrupted = [] def __init__(self, clVars): self.clVars = clVars self.varDiskData = clVars.zipVars('os_disk_dev', 'os_disk_format', 'os_disk_mount', 'os_disk_options', 'os_disk_part', 'os_disk_size') def addFileSystemCorrupted(self, fileSystem): """Add file system with error""" if not fileSystem in self.listFileSystemCorrupted: self.listFileSystemCorrupted.append(fileSystem) def getAllSupportFileSystemOpt(self): """Get list all file system""" return filter(lambda x: not x.startswith("_"), self._fileSystemOpt.keys()) +\ self._propertiesFileSystem.keys() def getAllAvailableFileSystemOpt(self): return filter(lambda x: x in ("default","noformat","defaultflash") or (not "makefs" in self._fileSystemOpt[x] or path.exists(self._fileSystemOpt[x]["makefs"])), self.getAllSupportFileSystemOpt()) def _getFileSystemData(self, realFileSystem): """Get data in _fileSystemOpt""" return self._fileSystemOpt.get(realFileSystem) def _getFileSystemAllOpt(self, realFileSystem): """Get all options from file system""" data = self._getFileSystemData(realFileSystem) if data: return list(set(data["options"])|\ set(self._fileSystemOpt["_all"]["options"])) else: return [] def _checkExistsOptions(self, realFileSystem, realOptions): """Check exists options""" allOptions = self._getFileSystemAllOpt(realFileSystem) if not allOptions: raise InstallError(_("Unsupported file system %s")%realFileSystem) for opt in realOptions: if opt and not opt in allOptions: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")%opt) def _checkFileSystemIncompatibleOpt(self, realFileSystem, realOptions): """Check incompatible options from realOptions""" # detect duplicate options dupOptions = filter(lambda x: realOptions.count(x)>1, set(realOptions)) if dupOptions: raise InstallError(_("Duplicated options %s")%", ".join(dupOptions)) realOptions = map(lambda x: x.split("=")[0], realOptions) self._checkExistsOptions(realFileSystem, realOptions) data = self._getFileSystemData(realFileSystem) if data: defIncompatibleOpt = self._fileSystemOpt["_all"]["incompatible"] defIncompatibleOpt = map(lambda x: map(lambda y: y, x), defIncompatibleOpt) listDefIncompatibleOpt = reduce(lambda x,y: x+y, defIncompatibleOpt, []) incompatibleOpt = data["incompatible"] for listOpt in incompatibleOpt: for opt in listOpt: if opt in listDefIncompatibleOpt: defIncompatibleOpt = filter(lambda x: not opt in x, defIncompatibleOpt) incompatibleOpt = defIncompatibleOpt + incompatibleOpt listIncompatibleOpt = reduce(lambda x,y: x+y, incompatibleOpt, []) for option in realOptions: if option in listIncompatibleOpt: dataOpt = filter(lambda x: option in x, incompatibleOpt) if dataOpt: listOpt = filter(lambda x: x!=option, dataOpt[0]) twoOptList = list(set(listOpt)&set(realOptions)) if twoOptList: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incompatible options") + ":"+\ " " + option + " " + _("and") +\ " " + ",".join(twoOptList)) def _checkPairOpt(self, realFileSystem, realOptions): """Check options from realOptions (option=value)""" # detect duplicate options dupOptions = filter(lambda x: realOptions.count(x)>1, set(realOptions)) if dupOptions: raise InstallError(_("Duplicated options %s")%", ".join(dupOptions)) splOptions = map(lambda x: x.split("=")[0], realOptions) self._checkExistsOptions(realFileSystem, splOptions) dictOpt = {} notPairOpt = [] for opt in realOptions: dataOpt = opt.split("=") if len(dataOpt)==2: nameOpt, valueOpt = dataOpt if not nameOpt in dictOpt: dictOpt[nameOpt] = [] dictOpt[nameOpt].append(valueOpt) elif len(dataOpt)>2: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")%opt) else: notPairOpt.append(opt) data = self._getFileSystemData(realFileSystem) if data: pairData = {} pairData.update(self._fileSystemOpt["_all"]["pair"]) pairData.update(data["pair"]) allPairOpt = pairData.keys() wrongOpt = list(set(allPairOpt)&set(notPairOpt)) if wrongOpt: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect options %s")\ %", ".join(wrongOpt)) for nameOpt in dictOpt.keys(): if not nameOpt in allPairOpt: self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")\ %"%s=%s"%(nameOpt,valueOpt)) checkValues = pairData[nameOpt] checkValuesOpt = checkValues["options"] # check options listValues = dictOpt[nameOpt] if type(checkValuesOpt)!=list: if len(listValues)>1: wrongOpt = ",".join(map(lambda x: "%s=%s"%(nameOpt,x), listValues)) self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")\ %wrongOpt) if not checkValuesOpt.search(listValues[0]): self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")\ %"%s=%s"%(nameOpt,listValues[0])) else: wrongValues = list(set(listValues)-set(checkValuesOpt)) if wrongValues: wrongOpt = ",".join(map(lambda x: "%s=%s"%(nameOpt,x), wrongValues)) self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incorrect option %s")\ %wrongOpt) checkValuesIncompOpt = checkValues["incompatible"] if checkValuesIncompOpt: incompValues = list(set(listValues)&\ set(checkValuesIncompOpt)) if len(incompValues)>1: wrongOpt = map(lambda x: "%s=%s"%(nameOpt,x), incompValues) self.addFileSystemCorrupted(realFileSystem) raise InstallError(_("Incompatible options") + ":"+\ " " + wrongOpt[0] + " " + \ _("and") + " " +\ ",".join(wrongOpt[1:])) def getDefaultOptFileSystem(self, fileSystem, devicetype="hdd"): """Get default properties for fileSystem""" if not fileSystem in self._propertiesFileSystem: fileSystem="default" if devicetype == "flash" and fileSystem=="default": fileSystem="defaultflash" if devicetype != "flash" and fileSystem=="defaultflash": fileSystem="default" propertiesFileSystem = self._propertiesFileSystem.copy() return propertiesFileSystem[fileSystem] def getDefaultOptMountPoint(self, mountPoint): """Get default properties for mount point disk""" if not mountPoint in self._diskDefaultMountPoints: if mountPoint.startswith('/'): mountPoint = "default" else: raise InstallError(_("Incorrect mount point %s")%mountPoint) propertiesMountPoints = self._diskDefaultMountPoints.copy() return propertiesMountPoints[mountPoint] def getDefaultOptSwap(self): """Get default properties for swap""" return self._swapDefaultMountPoint def getDefaultOptBind(self): """Get default properties for swap""" return self._bindDefaultMountPoint def _getDeviceType(self,dev): """Get device type, considing given by user param""" oldRootDev = self.clVars.Get('os_install_root_dev') self.clVars.Set('os_install_root_dev',dev,True) rootType = self.clVars.Get('os_install_root_type') self.clVars.Set('os_install_root_dev',oldRootDev,True) return rootType def __call__(self, optionsDict={}): """Convert dict options (bind options, swap options or disk options)""" optProperties = optionsDict.copy() # bind options if "srcMountPoint" in optProperties: # bind options optProperties["srcMountPoint"] = \ path.normpath(optProperties["srcMountPoint"]) if "destMountPoint" in optProperties: optProperties["destMountPoint"] = \ path.normpath(optProperties["destMountPoint"]) dictOptions = self.getDefaultOptBind().copy() dictOptions.update(optProperties) return dictOptions optDevice = optProperties["dev"] optProperties["dev"] = \ getUdevDeviceInfo(name=optDevice).get('DEVNAME',optDevice) optDevice = optProperties["dev"] dataPart = filter(lambda x: x[0]==optDevice, self.varDiskData) if not dataPart: dataPart = [["",False,"","","",""]] dev, format, mount, options, part, size = dataPart[0] dictUpdateProperty = {} if "mountPoint" in optProperties: # Disk options dictOptions = {} optFileSystem = optProperties["fileSystem"] if optProperties["mountPoint"]: optMountPoint = path.normpath(optProperties["mountPoint"]) else: optMountPoint = optProperties["mountPoint"] # if specified mount point empty of default - it is / if not optMountPoint or optMountPoint=="default": optMountPoint = "/" dictUpdateProperty["mountPoint"] = optMountPoint supportedFS = self.getAllSupportFileSystemOpt() reRootDirectories = re.compile("^/[^/]*/?$",re.S) if reRootDirectories.match(path.normpath(optMountPoint)): # check install type (flash or hdd) if self._getDeviceType(dev) != "flash": excludeFS = set(["vfat","ntfs","ntfs-3g"]) else: excludeFS = set(supportedFS) - \ set(["vfat","noformat","default"]) else: excludeFS = set([]) availableFS = self.getAllAvailableFileSystemOpt() # if fs not specified and current fs not supported if not optFileSystem: if not (format and format in \ set(availableFS)&set(supportedFS)-excludeFS) \ and optMountPoint == '/': optFileSystem = "default" else: dictUpdateProperty["fileSystem"] = format # if specified fs if optFileSystem: # if specified wrong fs if not optFileSystem in supportedFS: raise InstallError(_("Wrong file system option '%s'")\ %optFileSystem) if not optFileSystem in availableFS: raise InstallError(_("File system '%s' is not available")\ %optFileSystem) if optFileSystem in excludeFS: mp = optMountPoint if reRootDirectories.match(path.normpath(mp)) \ and self._getDeviceType(dev) == "flash": mp = "flash" raise InstallError( _("File system for '%(mp)s' should not be '%(opt)s'") %{'mp':mp, 'opt':optFileSystem}) if not "fileSystem" in dictOptions or \ optFileSystem == "default": dictOptions.update( self.getDefaultOptFileSystem(optFileSystem, self._getDeviceType(dev))) if optFileSystem == "noformat": if not format: raise InstallError(\ _("Partition %s is not formatted")%dev) elif format in excludeFS: mp = optMountPoint if reRootDirectories.match(path.normpath(mp)) \ and self._getDeviceType(dev) == "flash": mp = "flash" raise InstallError(\ _("File system for '%(mp)s' should not be '%(format)s'")\ %{'mp':mp,'format':format}) if not options: options = ["noatime"] dictOptions["fileSystem"] = format dictOptions["options"] = [] if optFileSystem in self._propertiesFileSystem: dictUpdateProperty["fileSystem"] = dictOptions["fileSystem"] optOptions = optProperties["options"] flagCheckOptOptions = True if optOptions: if optMountPoint != "/": dictUpdateProperty["options"] = optOptions else: flagCheckOptOptions = True optProperties = dict(filter(lambda x: x[1], optProperties.items())) optProperties.update(dictUpdateProperty) if dictOptions: dictDefault = dictOptions.copy() else: dictDefault = self.getDefaultOptMountPoint(optMountPoint).copy() dictDefault.update(optProperties) if flagCheckOptOptions: # Check mount options self._checkFileSystemIncompatibleOpt(dictDefault["fileSystem"], dictDefault["options"]) self._checkPairOpt(dictDefault["fileSystem"], dictDefault["options"]) return dictDefault else: # Swap options dictOptions = {} optFileSystem = "swap" if optFileSystem != format: dictUpdateProperty["isFormat"] = True dictOptions = self.getDefaultOptSwap().copy() dictOptions.update(optProperties) dictOptions.update(dictUpdateProperty) return dictOptions class cltCopy(scanDirectory): """Copy clt files Example: cltCopier = cltCopy(target="/targetdir") # copy all clt files from etc directory to /targetdir/etc cltCopier.performCopy('/etc') """ def __init__(self,target='/tmp'): self.target = target performCopy = scanDirectory.scanningDirectory def processingFile(self,pathname,prefix): try: if pathname.endswith(".clt"): targetDir = pathJoin(self.target,path.dirname(pathname)) if not path.exists(targetDir): os.makedirs(targetDir) copy2(pathname,pathJoin(self.target,pathname)) except Exception,e: raise InstallError(_("Failed to copy '%(src)s' to '%(dst)s'")% {'src':pathname,'dst':pathJoin(self.target,pathname)}) return True class otherfilesCopy(scanDirectory): """Copy some files Example: otherfilesCopier = otherfilesCopy(target="/targetdir") # copy need files from etc directory to /targetdir/etc otherfilesCopier.performCopy('/etc') """ def __init__(self,target='/tmp',reTest=".*"): self.target = target self.reTest = re.compile(reTest,re.S) performCopy = scanDirectory.scanningDirectory def processingFile(self,pathname,prefix): try: if self.reTest.search(pathname): targetDir = pathJoin(self.target,path.dirname(pathname)) if not path.exists(targetDir): os.makedirs(targetDir) copy2(pathname,pathJoin(self.target,pathname)) except Exception,e: raise InstallError(_("Failed to copy '%(src)s' to '%(dst)s'")% {'src':pathname,'dst':pathJoin(self.target,pathname)}) return True class cl_install(color_print, SignalInterrupt): """Primary class for templates appling and system installation""" def __init__(self): self.clVars = None self.clTempl = None self.listDisksOptions = [] self.listBindsOptions = [] self.listSwapsOptions = [] self.startMessage = "" self.lenStartMessage = 0 self.stdoutHide = None self.stderrHide = None Spinner().setWriteFunc(self.defaultPrint) cl_overriding.exit = installExit cl_overriding.printERROR = overprintERROR # refresh information about LVM refreshLVM() # refresh information about device in udevadm info refreshUdev() def setNoColor(self): self.color = False def initVars(self): """Primary initialization of variables""" self.clVars = DataVarsInstall() self.clVars.importInstall() self.clVars.flIniFile() def cmpInstallVersion(self): """Compare current and install version(build) Return: 1 - new version above current and installed 0 - new version equal current or installed -1 - new version less current or installed -2 - installed versin above current and new """ rootdev = self.clVars.Get('os_install_root_dev') d = DistributiveRepository()._getfromcontent(rootdev) curver = self.clVars.Get('os_linux_ver') curbuild = self.clVars.Get('os_linux_build') curver = (getTupleVersion(curver),curbuild) nextver = self.clVars.Get('os_install_linux_ver') nextbuild = self.clVars.Get('os_install_linux_build') nextver = (getTupleVersion(nextver),nextbuild) curnextres = cmp(nextver,curver) if d and "ver" in d: installedver = (getTupleVersion(d["ver"]), d["build"]) if installedver > curver: instnextres = cmp(nextver,installedver) if instnextres <= 0 and curnextres == 1: return -2 return instnextres return curnextres def printAllPartitonsTable(self): """Print install report""" title, headerList, dataList = self.generateTableAllPartitionData() tableObj = tableReport("", headerList, dataList) tableObj.printReport(False) def printLocationTables(self): """Print install report""" title, headerList, dataList = self.generateTableMountData() tableObj = tableReport("", headerList, dataList) tableObj.printReport(False) title, headerList, dataList = self.generateTableBindData() if dataList: tableObj = tableReport(title, headerList, dataList) tableObj.printReport(False) def printNetworkTables(self): """Print install report""" title, headerList, dataList = self.generateTableNetworkData() tableObj = tableReport("", headerList, dataList) tableObj.printReport(False) def printRouteTables(self): """Print install report""" title, headerList, dataList = self.generateTableRouteData() tableObj = tableReport("", headerList, dataList) tableObj.printReport(False) def printInfo(self,update=False): clGet = self.clVars.Get installedSystem = "%s %s"%(clGet('os_linux_name'), clGet('os_linux_ver')) mbrDevice = self.clVars.Get('os_install_mbr') if not mbrDevice in ("","off"): syspath = getUdevDeviceInfo(name=mbrDevice).get('DEVPATH','') if not syspath.startswith('/sys'): syspath = pathJoin('/sys',syspath) pathVendor = "%s/device/vendor"%syspath pathModel = "%s/device/model"%syspath if path.exists(pathVendor) and path.exists(pathModel): addonMbrInfo = " (%s %s)"% \ (open(pathVendor,'r').read().strip(), open(pathModel,'r').read().strip()) else: addonMbrInfo = "" mbrdisk = "%s%s"%(clGet('os_install_mbr'),addonMbrInfo) else: mbrdisk = _("will not be changed") flash = clGet('os_install_root_type')=="flash" pxe = clGet('os_install_pxe')=='on' pxeflash = flash or pxe usbhdd = clGet('os_install_root_type')=="usb-hdd" hdd = clGet('os_install_root_type')=="hdd" if not flash: musers = ", ".join(set(clGet('cl_migrate_user'))-set(['root'])) \ or _("none") else: musers = _("none") dnsNoValue = _("none") dhcps = self.clVars.Get('os_install_net_dhcp_set') if dhcps: if dhcps[0] == "on": dnsNoValue = _("DHCP") self.printSUCCESS(_("Installation") + " Calculate Linux") printData = [ [(_("System"),True), (_("Computer name"),clGet('os_install_net_hostname'),not pxeflash), (_("Domain name"),clGet('os_install_net_domain'),not pxeflash), (_("Users"), musers,not pxeflash), (_("Installed system"),installedSystem,True) ], [(_("Localization"),not pxeflash), (_("Language"), clGet('os_install_locale_lang'),True), (_("Keymap"),clGet('os_install_locale_xkbname'),True), (_("Timezone"),clGet('os_install_clock_timezone'),True), ], [(_("Network services"),hdd), (_("Network manager"),clGet('os_install_net_conf'),True), (_("PROXY"), clGet('os_install_proxy') or _("none"),True), (_("NTP"),clGet('os_install_ntp') or _("none"),True), (_("DNS"),clGet('os_install_net_dns') or dnsNoValue,True) ], [(_("Hardware"),True), (_("Machine hardware name"), clGet('os_install_arch_machine'),True), (_("Number of processors"),clGet('hr_cpu_num'),hdd), (_("Videocard"),clGet('hr_video_name'),hdd), (_("{0} video driver").format("Xorg"), clGet('os_install_x11_video_drv'),hdd), (_("Screen resolution"),clGet('os_install_x11_resolution'),hdd) ], [(_("Network devices"),not pxeflash), (self.printNetworkTables,None,True) ], [(_("Routes"),not pxeflash), (self.printRouteTables,None,True) ], [(_("Location"),not pxe), (_("Master boot record")+" (MBR)",mbrdisk,True), (self.printLocationTables,None,True) ], [(_("Perform pre-install checkups"),True)] ] for section in printData: sectionname,condition = section[0] # skip section if not (callable(condition) and condition() or \ not callable(condition) and condition ): continue self.defaultPrint("%s\n"%sectionname) for label, data, cond in section[1:]: if not (callable(cond) and cond() or \ not callable(cond) and cond ): continue if callable(label): label() else: self.printSUCCESS(label+": %s"%data) # preinstall checkups subname = self.clVars.Get('os_install_linux_subname') subname = (" %s"%subname) if subname else "" buildvar = self.clVars.Get('os_install_linux_build') build = "" if buildvar: build = " (build %s)"%buildvar if update: cmpres = self.cmpInstallVersion() image = self.clVars.Get('cl_image') if image and ( not update or cmpres > 0): deviceName = "" if image.startswith('/dev'): deviceImage = \ map(lambda x:x[1].rpartition(" ")[2], filter(lambda x:x[0]==image, self.clVars.zipVars("os_disk_dev","os_disk_content"))) if deviceImage: if deviceImage[0] == "livecd": deviceName = " " + _("on")+" CDROM (%s)"%image else: deviceName = " " + _("on")+" USB Flash (%s)"%image self.printSUCCESS(_("An update found")+deviceName+": %s %s%s%s\n"% (self.clVars.Get('os_install_linux_name'), self.clVars.Get('os_install_linux_ver'), subname,build)) else: if update and cmpres == -2: self.printWARNING(_("Update already installed.")) else: self.printWARNING(_("No update available.")) def canInstallGrub2(self,target): """Check that system has grub2 in current and installed system""" if self.clVars.Get('os_grub2_path'): return bool( filter(lambda x:x.startswith('grub-1.99'), listDirectory('/var/db/pkg/sys-boot'))) return False def prepareBoot(self,targetDistr): """Prepare system for boot""" if self.clVars.Get('os_install_root_type') == "flash": self.installSyslinuxBootloader(targetDistr) else: if self.canInstallGrub2(targetDistr): self.installGrub2Bootloader(targetDistr) else: self.installLegacyGrubBootloader(targetDistr) def getTargetDistributive(self,disk,fileSystem="reiserfs",isFormat=False, systemId=None,buildermode=False,pxemode=False): """Get target distributive by params""" rootLabelName = "%s-%s"%(self.clVars.Get('os_install_linux_shortname'), self.clVars.Get('os_install_linux_ver')) mapPartPT = dict(self.clVars.zipVars("os_disk_dev","os_disk_table")) if buildermode: return ScratchPartitionDistributive(disk,mdirectory="/mnt/install", check=True, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, rootLabel=rootLabelName, partitionTable=mapPartPT.get(disk,None)) elif pxemode: return PxeDistributive('/var/calculate/pxe') elif self.clVars.Get('os_install_root_type')=="flash": return FlashDistributive(disk,mdirectory="/mnt/install", check=True, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, partitionTable=mapPartPT.get(disk,None)) else: target = PartitionDistributive(disk,mdirectory="/mnt/install", check=True, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, rootLabel=rootLabelName, partitionTable=mapPartPT.get(disk,None)) noRootPartDisksOptions = filter(lambda x: x['mountPoint']!="/", self.listDisksOptions) flagMultipartition = False objMultiPartitions = False # Disk multipartitions if noRootPartDisksOptions: flagMultipartition = True objMultiPartitions = MultiPartitions() for diskOptions in noRootPartDisksOptions: dev = diskOptions["dev"] mountPoint = diskOptions["mountPoint"] fileSystem = diskOptions["fileSystem"] isFormat = diskOptions["isFormat"] systemId = diskOptions["systemId"] partitionTable = mapPartPT.get(dev,None) objMultiPartitions.addPartition(dev=dev, mountPoint=mountPoint, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, partitionTable=partitionTable) # Swap multipartitions if self.listSwapsOptions: flagMultipartition = True if not objMultiPartitions: objMultiPartitions = MultiPartitions() for diskOptions in self.listSwapsOptions: dev = diskOptions["dev"] mountPoint = "swap" fileSystem = diskOptions["fileSystem"] isFormat = diskOptions["isFormat"] systemId = diskOptions["systemId"] partitionTable = mapPartPT.get(dev,None) objMultiPartitions.addPartition(dev=dev, mountPoint=mountPoint, fileSystem=fileSystem, isFormat=isFormat, systemId=systemId, partitionTable=partitionTable) # Bind multipartitions if self.listBindsOptions: flagMultipartition = True if not objMultiPartitions: objMultiPartitions = MultiPartitions() for diskOptions in self.listBindsOptions: dev = diskOptions["srcMountPoint"] mountPoint = diskOptions["destMountPoint"] fileSystem = "bind" isFormat = diskOptions["isFormat"] objMultiPartitions.addPartition(dev=dev, mountPoint=mountPoint, fileSystem=fileSystem, isFormat=isFormat, systemId=None, partitionTable=None) if flagMultipartition: # Set Multipartition target.multipartition=objMultiPartitions return target def closeClTemplate(self): if self.clTempl: if self.clTempl.cltObj: self.clTempl.cltObj.closeFiles() self.clTempl.closeFiles() self.clTempl = None def applyTemplatesStartup(self): """Apply templates for root of system.""" #self.clVars.Set("cl_root_path","/", True) self.clVars.Set("cl_chroot_path","/", True) self.clTempl = template(self.clVars,cltFilter=False) dirsFiles = self.clTempl.applyTemplates() if self.clTempl.getError(): self.printERROR(self.clTempl.getError()) return False else: return dirsFiles def applyTemplatesFlash(self,directory): """Apply templates for root of system.""" #self.clVars.Set("cl_root_path",directory, True) self.clVars.Set("cl_chroot_path","/", True) self.clVars.Set("cl_chroot_grub","/", True) self.clVars.Set("cl_root_path",directory, True) self.clTempl = template(self.clVars,cltObj=False) dirsFiles = self.clTempl.applyTemplates() if self.clTempl.getError(): raise InstallError(self.clTempl.getError()) else: return dirsFiles def applyTemplates(self,directory,grubDirectory): """Apply templates for root of system.""" self.clVars.Set("cl_chroot_path",directory, True) self.clVars.Set("cl_chroot_grub",grubDirectory, True) clTemplateCltPath = \ filter(lambda x:path.exists(x), map(lambda x:pathJoin(directory,x), self.clVars.Get('cl_template_clt_path'))) self.clVars.Set('cl_template_clt_path',clTemplateCltPath,True) self.clTempl = template(self.clVars,cltFilter=False) dirsFiles = self.clTempl.applyTemplates() if self.clTempl.getError(): raise InstallError(self.clTempl.getError()) else: return dirsFiles def checkDuplicate(self,datalist,name,key=lambda x:x): """Check on duplicate and print error""" keydata = map(key,datalist) dupKey = set(filter(lambda x:keydata.count(x)>1, keydata)) if dupKey: self.printERROR(_("Duplicated {keyname}: {keylist}").format( keyname=name,keylist=",".join(dupKey))) return False return True def setVarList(self,varsList,matrix): """Set matrix to vars""" if not matrix: map(lambda x:self.clVars.Set(x,[],True),varsList) else: map(lambda x:self.clVars.Set(x[0],list(x[1]),True), zip(varsList,zip(*matrix))) def setNetwork(self,ipaddrs,dhcps,routes): """Set network configuration""" def changeIpData(ipdata): iface,ipaddr,cidr,dhcpset = ipdata if iface in dhcps: if dhcpset == "off": invalidRouteIface.append(iface) dhcpset = "on" cidr = "" ipaddr = "" elif iface in dictIpAddr: newipaddr,op,newcidr = dictIpAddr[iface].partition('/') if dhcpset == "on" or newipaddr != ipaddr or newcidr != cidr: invalidRouteIface.append(iface) ipaddr,cidr = newipaddr,newcidr dhcpset = "off" return (iface,ipaddr,cidr,dhcpset) def removeInvalidRoutes(routedata): """Remove route for device with new ip""" network,gw,dev,src = routedata if dev in invalidRouteIface: return False return True def removeSpecifiedRoutes(routedata): """Remove route for user specified""" network,gw,dev,src = routedata if network in specifedNet: return False return True def specifedRoutes(routes,ipAddrs,routedata): NET,GW,DEV,SRC=0,1,2,3 nets = filter(lambda net:net != "default", map(lambda x:x[NET],routes)+map(lambda x:x[NET],routedata)) routes = filter(lambda x:x[GW] or x[SRC],routes) wrongGws = map(lambda x:x[GW], filter(lambda x:not ip.isIpInNet(x[GW], *(set(nets)-set([x[NET]]))), filter(lambda x:x[GW], routes))) if wrongGws: raise InstallError(_("Gateways %s is unreachable")% (",".join(wrongGws))) wrongIps = map(lambda x:x[SRC], filter(lambda x:not x[SRC] in ipAddrs, filter(lambda x:x[SRC],routes))) if wrongIps: raise InstallError(_("Wrong ip addresse %s in source IP")% (",".join(wrongIps))) newroutes = [] for network,gw,dev,src in routedata+routes: if not dev: gwnetwork = ip.isIpInNet(gw,*nets)[0] dev = filter(lambda x:x[NET]==gwnetwork, routedata+newroutes) if not dev: raise InstallError( _("Failed to determine the device for network %s")% network) dev = dev[0][DEV] if not gw and not src: continue newroutes.append((network,gw,dev,src)) return newroutes def standardRoutes(ipMatrix,needDev): IFACE,IP,CIDR,DHCP = 0,1,2,3 return map(lambda x:(ip.getIpNet(x[IP],cidr=x[CIDR]), "",x[IFACE],x[IP]), filter(lambda x:x[DHCP] =="off" and x[IFACE] in needDev, ipMatrix)) # check interfaces getVar = self.clVars.Get interfaces = getVar('os_install_net_interfaces') if interfaces: defaultIface = interfaces[0] else: defaultIface = "" ipaddrs = map(lambda x: x if len(x)==2 else (defaultIface,x[0]), ipaddrs) specifiedIface = dhcps + map(lambda x:x[0],ipaddrs) routeIface = filter(lambda x:x, map(lambda x:x[2],filter(lambda x:len(x)>2,routes))) wrongIface = set(specifiedIface+routeIface)-set(interfaces) # check correct iface if wrongIface: self.printERROR(_("Wrong interface: %s")%",".join(wrongIface)) return False # check dup iface if not self.checkDuplicate(specifiedIface,_("interfaces")): return False # check dup ip if not self.checkDuplicate(ipaddrs,_("addresses"),key=lambda x:x[1]): return False dictIpAddr = dict(ipaddrs) # set user data to variables ipVars = map(lambda x:'os_install_net_%s'%x, ('interfaces', 'ip', 'cidr', 'dhcp_set')) invalidRouteIface = [] self.setVarList(ipVars, map(changeIpData, self.clVars.zipVars(*ipVars))) specifedNet = map(lambda x:x[0],routes) routeVars = map(lambda x:'os_install_net_route_%s'%x, ('network', 'gw', 'dev', 'src')) try: self.setVarList(routeVars, specifedRoutes(routes,getVar('os_install_net_ip'), filter(removeSpecifiedRoutes, standardRoutes(self.clVars.zipVars(*ipVars),invalidRouteIface)+ filter(removeInvalidRoutes, self.clVars.zipVars(*routeVars))))) except InstallError,e: self.printERROR(str(e)) return False # check dup nets if not self.checkDuplicate(routes,_("networks"),key=lambda x:x[0]): return False return True def setDisks(self,listDisks,listBinds,listSwaps): """Set data for installation partitions""" convObj = convertDictOpt(self.clVars) try: listDisks = map(convObj, listDisks) # detect previous system if not specified root partition if not filter(lambda x: x['mountPoint'] == '/',listDisks): prevRootDev = self.clVars.Get('os_install_dev_from') if prevRootDev: listDisks += map(convObj, [{'mountPoint': '', 'options': ['noatime'], 'dev': prevRootDev, 'fileSystem': ''}]) listBinds = map(convObj, listBinds) listSwaps = map(convObj, listSwaps) except InstallError,e: self.printERROR(str(e)) if convObj.listFileSystemCorrupted: self.printWARNING(_("See 'man mount' for file system") + " "+\ ", ".join(convObj.listFileSystemCorrupted)) return False # break perform if disk params empty and os_install_dev_from empty if not (listDisks or listSwaps or listBinds): return True usedDevicesOnlyDisks = map(lambda x:x['dev'],listDisks) usedDevicesOnlySwap = map(lambda x:x['dev'],listSwaps) usedDevices = map(lambda x:x['dev'],listSwaps)+usedDevicesOnlyDisks usedMP = map(lambda x:x['mountPoint'],listDisks) + \ map(lambda x:x['destMountPoint'],listBinds) # check mount options for scratch and flash if filter(lambda x: x != '/', usedMP): if self.clVars.Get('os_install_scratch') == "on": self.printERROR( _("Builder mode does not support multipartition install")) return False # check specified devices wrongDevices = list(set(usedDevicesOnlyDisks) - \ set(self.clVars.Get('os_disk_dev'))) wrongDevices = wrongDevices + list(set(usedDevicesOnlySwap) - \ set(self.clVars.Get('os_disk_dev')+["none"])) if wrongDevices: self.printERROR(_("Incorrect device '%s'")%wrongDevices[0]) return False # detect using extended partition extendedPartitions = map(lambda x: x[1], filter(lambda x: x[0]=="extended", zip(self.clVars.Get('os_disk_part'), self.clVars.Get('os_disk_dev')))) usingExtPart = list(set(usedDevices)&set(extendedPartitions)) if usingExtPart: self.printERROR( _("Unable to use the extended partition %s for installation")% usingExtPart[0]) return False # detect using CDROM disks cdromPartitions = map(lambda x: x[1], filter(lambda x: "cdrom" in x[0], zip(self.clVars.Get('os_disk_type'), self.clVars.Get('os_disk_dev')))) usingCdromPart = list(set(usedDevices)&set(cdromPartitions)) if usingCdromPart: self.printERROR(_("Unable to use CDROM %s for installation")% usingCdromPart[0]) return False # detect using RAID member disks raidMemberData = filter(lambda x: "raidmember" in x[0], zip(self.clVars.Get('os_disk_type'), self.clVars.Get('os_disk_dev'))) raidMemberPartitions = map(lambda x:x[1],raidMemberData) usingRaidMemberPart = list(set(usedDevices)&set(raidMemberPartitions)) if usingRaidMemberPart: raidMemberData = filter(lambda x:x[1] in usingRaidMemberPart, raidMemberData)[0][0] raidMemberData = raidMemberData.rpartition("raidmember(")[2] raidMemberData = raidMemberData.partition(")")[0] self.printERROR(_("Unable to use active {typepart} member {part} " "for installation").format( typepart="RAID",part=usingRaidMemberPart[0])) self.printERROR( _("To use this partition, you have to stop RAID %s")% raidMemberData) self.printERROR(" mdadm -S %s"%raidMemberData) return False # detect using LVM member disks lvmMemberData = filter(lambda x: "lvmmember" in x[0], zip(self.clVars.Get('os_disk_type'), self.clVars.Get('os_disk_dev'))) lvmMemberPartitions = map(lambda x:x[1],lvmMemberData) usingLvmMemberPart = list(set(usedDevices)&set(lvmMemberPartitions)) if usingLvmMemberPart: lvmMemberData = filter(lambda x:x[1] in usingLvmMemberPart[0], lvmMemberData)[0][0] lvmMemberData = lvmMemberData.rpartition("lvmmember(")[2] lvmMemberData = lvmMemberData.partition(")")[0] prop = getUdevDeviceInfo(name=lvmMemberData) vgName = prop.get('DM_VG_NAME','') self.printERROR(_("Unable to use active {typepart} member {part} " "for installation").format( typepart="LVM",part=usingLvmMemberPart[0])) self.printERROR( _("To use this partition, you have to remove LVM %s")% lvmMemberData) self.printERROR(" vgremove %s"%vgName) self.printERROR(" pvremove %s"%usingLvmMemberPart[0]) return False srcMountPoints = map(lambda x:x['srcMountPoint'],listBinds) destMountPoints = map(lambda x:x['destMountPoint'],listBinds) wrongBind = filter(lambda x:x in destMountPoints,srcMountPoints) if wrongBind: incompBind = filter(lambda x:x[1]==wrongBind[0], zip(srcMountPoints,destMountPoints)) self.printERROR(_("Source directory %(src)s already used " "for binding '%(bindSrc)s' to '%(bindDst)s'")\ %{'src':wrongBind[0], 'bindSrc':incompBind[0][0], 'bindDst':incompBind[0][1]}) return False # Check bind params wrongBind = filter(lambda x:not x[0].startswith("/") or not x[1].startswith("/") and x[1] != "none", zip(srcMountPoints,destMountPoints)) if wrongBind: self.printERROR(_("Incorrect mount point (bind '%(bindSrc)s' to "\ "'%(bindDst)s')")\ %{'bindSrc':wrongBind[0][0], 'bindDst':wrongBind[0][1]}) return False # Check '/' in start path wrongMP = filter(lambda x: not x.startswith("/") and x!="none", usedMP) + \ filter(lambda x: not x.startswith("/"), map(lambda x:x['srcMountPoint'],listBinds)) if wrongMP: self.printERROR(_("Incorrect mount point '%s'")%wrongMP[0]) return False # detect duplicate devices dupDevices = list(set(filter(lambda x:usedDevices.count(x)>1, usedDevices))) if dupDevices: self.printERROR(_("Device '%s' is used twice")%dupDevices[0]) return False # detect duplicate mount points dupMP = list(set(filter(lambda x:usedMP.count(x)>1 and x != "none", usedMP))) if dupMP: self.printERROR(_("Mount point '%s' is used twice")%dupMP[0]) return False rootdevs = map(lambda x:x['dev'], filter(lambda x:"mountPoint" in x and \ "dev" in x and \ x['mountPoint']=='/', listDisks)) if rootdevs: self.clVars.Set('os_install_root_dev',rootdevs[0],True) rootType = self.clVars.Get('os_install_root_type') curRootType = self.clVars.Get('os_root_type') def clearParam(data,isswap): if rootType == 'usb-hdd' and curRootType != "usb-hdd": return "" if builderMode: if len(listSwaps) == 0 and isswap == "swap": return data else: if len(listSwaps) == 0 or isswap != "swap": return data return "" builderMode = self.clVars.Get('os_install_scratch') == "on" clearBuilder = lambda data,isswap: \ "" if builderMode and isswap != "swap" else data # get hash from current variables DEV,MOUNT,FS,OPTS = 0,1,2,3 devMount = dict(map(lambda x:(x[DEV], {'mountPoint':clearParam(x[MOUNT],x[MOUNT]), 'fileSystem':x[FS], 'options':clearParam(x[OPTS],x[MOUNT]), 'isFormat':""}), zip(self.clVars.Get('os_disk_dev'), self.clVars.Get('os_install_disk_mount'), self.clVars.Get('os_install_disk_format'), self.clVars.Get('os_install_disk_options')))) curDevMount = dict(zip(self.clVars.Get('os_disk_dev'), self.clVars.Get('os_disk_mount'))) dictMountDev = dict(zip(self.clVars.Get('os_install_disk_mount'), self.clVars.Get('os_disk_dev'))) # update current variable by cmd params for diskData in listDisks+listSwaps: dev = diskData['dev'] # skip none swap device if dev == "none": continue mountPoint = diskData.get('mountPoint','swap') isFormat = diskData['isFormat'] if mountPoint == "none": mountPoint = "" curMP = curDevMount[dev] if curMP and ( curMP != mountPoint and isFormat or curMP == '/' ): self.printERROR(_("Specified disk '%s' mounted to")\ %dev + " " + _("'%s' in the current system")\ %curMP) return False else: if mountPoint and mountPoint in dictMountDev and \ mountPoint != "swap": devMount[dictMountDev[mountPoint]]['mountPoint'] = '' devMount[dev]['mountPoint'] = mountPoint devMount[dev]['options'] = ",".join(diskData['options']) devMount[dev]['fileSystem'] = diskData['fileSystem'] if isFormat: devMount[dev]['isFormat'] = "yes" if builderMode: bindDestSrc = {} bindSrcDest = {} else: bindDestSrc =dict(zip(self.clVars.Get('os_install_bind_mountpoint'), self.clVars.Get('os_install_bind_path'))) bindSrcDest = dict(zip(self.clVars.Get('os_install_bind_path'), self.clVars.Get('os_install_bind_mountpoint'))) for bindData in listBinds: srcMountPoint = bindData['srcMountPoint'] destMountPoint = bindData['destMountPoint'] if destMountPoint in dictMountDev: devMount[dictMountDev[destMountPoint]]['mountPoint'] = '' if destMountPoint == "none" and srcMountPoint in bindSrcDest and \ bindSrcDest[srcMountPoint] in bindDestSrc: bindDestSrc.pop(bindSrcDest[srcMountPoint]) bindSrcDest.pop(srcMountPoint) else: bindDestSrc[destMountPoint] = srcMountPoint if destMountPoint in bindSrcDest: bindDestSrc.pop(bindSrcDest[destMountPoint]) bindSrcDest[srcMountPoint] = destMountPoint # update install root dev rootDev = filter(lambda x:x[1]['mountPoint']=='/',devMount.items()) if not rootDev: self.printERROR(_("The root partition must be specified")) return False self.clVars.Set('os_install_root_dev',rootDev[0][0],True) osInstallRootType = self.clVars.Get('os_install_root_type') # update bind variables by new hash if osInstallRootType != "flash": new_bind_dest, new_bind_src = \ reduce(lambda x,y:[x[0]+[y[0]],x[1]+[y[1]]], sorted(bindDestSrc.items()) , [[]]*2) # discard all bind point for flash installation else: new_bind_dest = [] new_bind_src = [] if filter(lambda x: x != '/', usedMP): self.printERROR( _("Installation to flash disk is not supported for " "multipartition install")) return False if filter(lambda x:x['dev']!="none",listSwaps): self.printERROR( _("Installation to flash disk is not " "supported for swap disks")) return False if builderMode: self.printERROR( _("Installation to flash disk is not supported" " in builder mode")) return False # receive substitution func. Discard all mp, exclude '/' for flash if osInstallRootType != "flash": substitution = lambda data,mp: data else: substitution = lambda data,mp: data if mp == '/' else "" separateDevice = lambda device: map( lambda x: int(x) if x.isdigit() else x, re.findall('\d+|\D+',device)) # update variables by new hash new_mount, new_format, new_isformat, new_options= \ reduce(lambda x,y:[x[0]+[substitution(devMount[y]['mountPoint'], devMount[y]['mountPoint'])], x[1]+[substitution(devMount[y]['fileSystem'], devMount[y]['mountPoint'])], x[2]+[substitution(devMount[y]['isFormat'], devMount[y]['mountPoint'])], x[3]+[substitution(devMount[y]['options'], devMount[y]['mountPoint'])]], sorted(devMount.keys(),key=separateDevice),[[]]*4) map(lambda x:self.clVars.Set(x[0],x[1],True), (('os_install_disk_mount',new_mount), ('os_install_disk_mount',new_mount), ('os_install_disk_format',new_format), ('os_install_disk_perform_format',new_isformat), ('os_install_disk_options',new_options), ('os_install_bind_path',new_bind_src), ('os_install_bind_mountpoint',new_bind_dest))) if not self.clVars.Get('os_grub2_path'): if not self.checkForLegacyGrub(): return False else: if not self.checkForGrub2(): return False return True def checkForGrub2(self): """Check current disk configuration for installation for install GRUB2""" bootDiskType = self.varSelect("os_disk_type", where="os_install_disk_mount", eq="/boot") rootDiskType = self.varSelect("os_disk_type", where="os_install_disk_mount", eq="/") grubDiskType = bootDiskType or rootDiskType if "lvm-raid" in grubDiskType: self.printERROR( _("Grub does not support booting from a RAID assembled from LVM.") + " " + _("Try to use a separate /boot partition")) return False if grubDiskType.count("raid")>1: self.printERROR( _("Grub does not support booting from a RAID assembled " "from another RAID.") + " " + _("Try to use a separate /boot partition")) return False return True def checkForLegacyGrub(self): """Check current disk configuration for installation for install legacy grub""" bootDiskType = self.varSelect("os_disk_type", where="os_install_disk_mount", eq="/boot") rootDiskType = self.varSelect("os_disk_type", where="os_install_disk_mount", eq="/") bootDiskFormat = self.varSelect("os_install_disk_format", where="os_install_disk_mount", eq="/boot") rootDiskFormat = self.varSelect("os_install_disk_format", where="os_install_disk_mount", eq="/") bootDiskType = bootDiskType or rootDiskType bootDiskFormat = bootDiskFormat or rootDiskFormat if "lvm" in bootDiskType or "raid" in bootDiskType: self.printERROR( _("Legacy grub does not support boot from raid or lvm " "without separate /boot partition")) return False if bootDiskFormat in ("btrfs","nilfs2"): self.printERROR( _("Legacy grub does not support booting from %s without " "separate /boot partition")%bootDiskFormat) return False return True def setUsers(self,listUsers,autologinUser): """Set users data (migration)""" if autologinUser == "none": autologinUser = "" if autologinUser or autologinUser == "": self.clVars.Set('cl_autologin', autologinUser, force=True) else: autologinUser = self.clVars.Get('cl_autologin') autologinUser = [autologinUser] if autologinUser else [] listUsers = listUsers or [] if listUsers or autologinUser: migrateUsers = list(set(listUsers+autologinUser)) migrateUsers.sort() migrateUsers = ["root"] + filter(lambda x: x!="root", migrateUsers) self.clVars.Set('cl_migrate_user', migrateUsers, force=True) return True def setBR(self, mbrDisk): """Set boot record on disk by param or get from variables""" bootDiskGrub = "" if mbrDisk == "off": self.clVars.Set('os_install_mbr',"",force=True) return True elif mbrDisk: if filter(lambda x: x == mbrDisk, self.clVars.Get('os_device_dev')): self.clVars.Set('os_install_mbr', mbrDisk, force=True) else: self.printERROR(_("Failed to find disk '%s'")%mbrDisk) return False return True def createListOptions(self): """Create listDisksOptions, listSwapsOptions and listBindOptions by variables""" diskData = zip(self.clVars.Get('os_disk_dev'), self.clVars.Get('os_install_disk_mount'), self.clVars.Get('os_install_disk_format'), self.clVars.Get('os_install_disk_options'), self.clVars.Get('os_install_disk_perform_format')) bindData = zip(self.clVars.Get('os_install_bind_path'), self.clVars.Get('os_install_bind_mountpoint')) listToOptDict = lambda x: {'dev':x[0], 'mountPoint':x[1], 'fileSystem':x[2], 'options':x[3].split(','), 'isFormat':True if x[4] == "yes" else False} listToOptDictBind = lambda x:{'srcMountPoint':x[0], 'destMountPoint':x[1], 'options':['bind'], 'isFormat':False, 'fileSystem':'none'} self.listDisksOptions = map(listToOptDict, filter(lambda x:x[1] and x[1] != "swap", diskData)) self.listSwapsOptions = map(listToOptDict, filter(lambda x: x[1] == "swap", diskData)) self.listBindsOptions = map(listToOptDictBind,bindData) # update system id osDiskDevices = self.clVars.Get('os_disk_dev') updateIdDict = dict(map(lambda x:(x[0],x[2]),filter(lambda x:x[1]!=x[2], zip(self.clVars.Get('os_disk_dev'), self.clVars.Get('os_disk_id'), self.clVars.Get('os_install_disk_id'))))) for disk in self.listDisksOptions + self.listSwapsOptions: if disk['dev'] in updateIdDict: disk['systemId'] = updateIdDict[disk['dev']] else: disk['systemId'] = None return True def setInstallOptions(self, listDisks, listBinds, listSwaps, listUsers, autologinUser, brDisk): """Set install options (set users, disks and boot record""" try: if self.setUsers(listUsers,autologinUser) and \ self.setDisks(listDisks,listBinds,listSwaps) and \ self.setBR(brDisk): return self.createListOptions() else: return False except InstallError,e: self.printERROR(str(e).strip()) return False def getDeviceByField(self,field,value, secondPrefix="os_disk"): """Get device by fields (install load format uuid grub part name)""" return self.getFieldByField('dev',field,value, secondPrefix=secondPrefix) def getFieldByField(self,resField,field,value, firstPrefix="os_disk", secondPrefix="os_disk"): res = filter(lambda x: x[1] == value, zip(self.clVars.Get('%s_%s'%(firstPrefix,resField)), self.clVars.Get('%s_%s'%(secondPrefix,field)))) or\ [("","")] return res[0][0] def getFieldByDevice(self,field,device): """Get value of field by device""" device_hash = self.clVars.Get('os_disk_hash') if device in device_hash and field in device_hash[device]: return device_hash[device][field] else: return "" def setActivePartition(self,partition): """TODO: don't work with GPT. Don't work must be rewrite!!!!!""" reActive = re.compile('^%s\s*[*]'%partition) device = filter(lambda x:x in partition, self.clVars.Get('os_device_dev')) if not device: raise DistributiveError(_("Failed to find the parent device")) device = device[0] fdiskProcess = process("/sbin/fdisk","-l",device) if fdiskProcess.failed(): raise DistributiveError(_("Failed to get device information\n%s")% fdiskProcess.read()) if not filter(reActive.search,fdiskProcess): grubDisk = self.getFieldByField("grub","mount","/", secondPrefix="os_install_disk") if grubDisk and grubDisk.rpartition(',')[2].isdigit(): fdiskProcess = process("/sbin/fdisk", device) fdiskProcess.write("a\n%d\nw\n"% (int(grubDisk.rpartition(',')[2])+1)) if fdiskProcess.success(): return True if filter(reActive.search,process("/sbin/fdisk", "-l",device)): return True raise DistributiveError(_("Failed to set the active partition")) else: return True def installSyslinuxBootloader(self,target): """Install boot loader by syslinux Perform syslinux installation to flash. """ ddProcess = process("/bin/dd","if=/usr/share/syslinux/mbr.bin", "of=%s"%self.clVars.Get('os_install_mbr'), stderr=STDOUT) if ddProcess.failed(): raise DistributiveError( _("Failed to write the master boot record\n%s")% ddProcess.read()) target.close() installRootDev = self.clVars.Get('os_install_root_dev') syslinuxProcess = process("/usr/bin/syslinux", installRootDev, stderr=STDOUT) if syslinuxProcess.failed(): raise DistributiveError(_("Failed to install syslinux\n%s")% syslinuxProcess.read()) # is partition active return self.setActivePartition(self.clVars.Get('os_install_root_dev')) def varSelect(self,selField,where="os_disk_dev",eq=""): """Select value from os_disk/device matrix""" res = filter(lambda x: x[1] == eq, zip(self.clVars.Get(selField), self.clVars.Get(where))) or\ [("","")] return res[0][0] def getPartitionForParted(self,partition): """Get partition info for parted exectution""" # get disk num and partitin num bootMap = \ self.varSelect("os_disk_grub",where="os_disk_dev",eq=partition) # check valid numbers deviceNumber,op,partitionNumber = bootMap.partition(',') if not deviceNumber.isdigit() or \ not partitionNumber.isdigit(): return (False,False) # get partition number partitionNumber = int(partitionNumber)+1 # get device name deviceName = self.varSelect("os_device_dev",where="os_device_map", eq=int(deviceNumber)) if deviceName: return (deviceName,partitionNumber) return (False,False) def setBiosGrubForBootPartition(self): """Set bios_grub flag for boot partition in gpt (WRONG)""" for bootPath in ("/boot","/"): # get grub disk by mount point bootPart = self.varSelect( "os_disk_part",where="os_install_disk_mount",eq=bootPath) if bootPart: if bootPart == "gpt": bootPart = self.varSelect( "os_disk_dev",where="os_install_disk_mount",eq=bootPath) deviceName,partitionNumber = \ self.getPartitionForParted(bootPart) cmdParted = varsShare().getProgPath('/usr/sbin/parted') if not cmdParted: return False partedProcess = process(cmdParted,deviceName, "set",str(partitionNumber),"bios_grub","on") return partedProcess.success() return True return False def installGrub2Bootloader(self,target): """Install grub2 boot loader""" cmdGrubInstall = self.clVars.Get('os_grub2_path') #if not self.setBiosGrubForBootPartition(): # raise DistributiveError( # _("Failed to set bios_grub flag for the boot partition")) if not cmdGrubInstall: raise DistributiveError(_("Failed to install the bootloader")) mbrDisk = self.clVars.Get('os_install_mbr') process("sync").success() grubProcess = process(cmdGrubInstall, "--boot-directory=%s"%target.getBootDirectory(), mbrDisk, "-f", stderr=STDOUT,envdict=os.environ) if grubProcess.failed(): raise DistributiveError(_("Failed to install the bootloader")) def installLegacyGrubBootloader(self,target): """Install boot loader Perform grub installation to disk, which has root partition """ cmdGrub = varsShare().getProgPath('/sbin/grub') if not cmdGrub: raise DistributiveError(_("Failed to install the bootloader")) grubProcess = process(cmdGrub, "--device-map=%s/boot/grub/device.map"%target.getDirectory(), "--batch",stderr=STDOUT) for bootPath in ("/boot","/"): # get grub disk by mount point bootDisk = self.varSelect( "os_disk_grub",where="os_install_disk_mount",eq=bootPath) if bootDisk: break mbrDisk = self.clVars.Get('os_install_mbr') mbrDiskNum = self.varSelect( "os_device_map",where="os_device_dev",eq=mbrDisk) if not mbrDiskNum and mbrDiskNum != 0: raise DistributiveError(_("Failed to determine mbr")) for line in ("root (hd%s)"%bootDisk, "setup (hd%d)"%mbrDiskNum, "quit"): grubProcess.write("%s\n"%line) if grubProcess.failed(): raise DistributiveError(_("Failed to install the bootloader")) def convertTypeToScheme(self,data): """Convert os_disk_type to human readable names""" if type(data) == tuple: diskScheme, driveType = data else: diskScheme, driveType = data,"" res = "" if diskScheme.endswith("raid-lvm"): return _("LVM on RAID") elif "disk-partition" == diskScheme and driveType == "flash": return _("Partition on flash") elif "disk-partition" == diskScheme and driveType == "usb-hdd": return _("Partition on USB-HDD") elif "disk-partition" == diskScheme: return _("Partition on disk") elif "raid-partition" == diskScheme: return _("Partition on RAID") elif "raidmember" in diskScheme: diskScheme = diskScheme.rpartition("raidmember(")[2] diskScheme = diskScheme.partition(")")[0] return _("RAID %s member")%diskScheme elif "lvmmember" in diskScheme: lvms = [] while "lvmmember" in diskScheme: diskScheme,op,data = diskScheme.rpartition("lvmmember(") lvms.append(data.partition(")")[0]) return _("LVM %s member")%",".join(lvms) elif "disk" == diskScheme: return _("Disk without partitions") elif "lvm" in diskScheme: return _("LVM") elif "raid" in diskScheme: return _("RAID") elif "cdrom" in diskScheme: return _("CDROM") else: return _("Partition") def generateTableAllPartitionData(self): """Generate table for all partitions""" title = _("Available partitions") headerList = [_("Size"),_("Device"),_("Label"),_("Mount point"), _("File system"), _("Type"),_("OS")] deviceHash = self.clVars.Get('os_device_hash') diskHash = self.clVars.Get('os_disk_hash') getTypeByDevice = lambda x: \ deviceHash.get(diskHash[x].get('parent',{}),{}).get('type','') return title, headerList, zip(self.clVars.Get('os_disk_size'), self.clVars.Get('os_disk_dev'), self.clVars.Get('os_disk_name'), self.clVars.Get('os_disk_mount'), self.clVars.Get('os_disk_format'), map(self.convertTypeToScheme, zip(self.clVars.Get('os_disk_type'), map(getTypeByDevice,self.clVars.Get('os_disk_dev')))), self.clVars.Get('os_disk_content')) def generateTableMountData(self): """Get data from print table""" title = _("Location") allDevicesOpt = self.listDisksOptions + self.listSwapsOptions listIsFormat = [] for dev in self.clVars.Get('os_disk_dev'): devCmdOpt = filter(lambda x: x['dev']==dev, allDevicesOpt) if devCmdOpt: if devCmdOpt[0]["isFormat"]: listIsFormat.append(_("Yes")) else: listIsFormat.append("") else: listIsFormat.append("") fileSystemData = zip(self.clVars.Get('os_install_disk_format'), self.clVars.Get('os_disk_format')) listFileSystem = map(lambda x: x[0] if x[0] else x[1], fileSystemData) #fileSystemData = zip(listFileSystem, #self.clVars.Get('os_disk_format')) #listFileSystem = map(lambda x:\ #x[0] if x[0]==x[1] else "%s -> %s" %(x[1], x[0]), #fileSystemData) listMountPoint = map(lambda x: "" if x=="swap" else x, self.clVars.Get('os_install_disk_mount')) if self.clVars.Get('os_install_scratch') == "on": listMountPoint = map(lambda x: "builder" if x == "/" else x, listMountPoint) partData = zip(self.clVars.Get('os_disk_size'), self.clVars.Get('os_disk_part')) listSize = map(lambda x: "" if x[1]=="extended" else x[0], partData) if self.clVars.Get('os_install_root_type') == 'flash': headerList = [_("Size"),_("Device"),_("File system"), _("Format"), _("Partition")] colnum = 2 else: headerList = [_("Size"),_("Device"),_("Directory"), _("File system"),_("Format"), _("Partition")] colnum = 3 dataList = map(lambda x:x[:colnum]+x[3:-1], filter(lambda x:x[-1] != "", zip(listSize, self.clVars.Get('os_disk_dev'), listMountPoint, listFileSystem, listIsFormat, map(lambda x:x[0] or x[1], zip(self.clVars.Get('os_disk_part'), map(self.convertTypeToScheme, self.clVars.Get('os_disk_type')))), self.clVars.Get('os_install_disk_mount')))) return title, headerList, dataList def generateTableBindData(self): """Get bind data for print table""" title = _("Bind mounts") headerList = [_("Source directory"),_("Mount point")] return title, headerList, zip(self.clVars.Get('os_install_bind_path'), self.clVars.Get('os_install_bind_mountpoint')) def generateTableNetworkData(self): """Get bind data for print table""" def ipInformation(listIpMaskDhcp): ipaddr,cidr,dhcp = listIpMaskDhcp if dhcp == "on": return _("DHCP") elif ipaddr: return "{ip}/{cidr}".format(ip=ipaddr,cidr=cidr) else: return _("Off") clGet = self.clVars.Get title = _("Network devices") headerList = [_("Device"),_("Name"),_("MAC address"),_("IP address")] return title, headerList, zip(clGet('os_install_net_interfaces'), clGet('os_install_net_name'), clGet('os_install_net_mac'), map(ipInformation, zip(clGet('os_install_net_ip'), clGet('os_install_net_cidr'), clGet('os_install_net_dhcp_set')))) def generateTableRouteData(self): """Get bind data for print table""" clGet = self.clVars.Get title = _("Routes") headerList = [_("Device"),_("Network"),_("Gateway"),_("Source IP")] return title, headerList, zip(clGet('os_install_net_route_dev'), clGet('os_install_net_route_network'), clGet('os_install_net_route_gw'), clGet('os_install_net_route_src')) + \ map(lambda x:(x[0],_("DHCP"),_("DHCP"),_("DHCP")), filter(lambda x:x[1]=='on',zip(clGet('os_install_net_interfaces'), clGet('os_install_net_dhcp_set')))) def getPwdHashUser(self, userName, stdinRead=False): if stdinRead: try: userPwd = sys.stdin.readline().rstrip() except EOFError: raise KeyboardInterrupt() else: cl_overriding.printSUCCESS(_("Enter the password for user %s")% userName) try: userPwd = getUserPassword() while userPwd is False: if get_install_errors(): for line in filter(lambda x:x, pop_install_errors().split('\n')): self.printERROR(line) userPwd = getUserPassword() except EOFError: raise KeyboardInterrupt() encryptObj = encrypt() if not userPwd: raise InstallError(_("Failed to find the password for user %s")\ %userName) return False pwdHash = encryptObj.getHashPasswd(userPwd, "shadow_ssha256") if pwdHash is False: raise InstallError() return pwdHash def getNamesAddUsers(self): """Get names added users""" return map(lambda x: x[0], filter(lambda x: x[1]=="yes",\ zip(self.clVars.Get("cl_migrate_user"), self.clVars.Get("cl_migrate_user_pwd")))) def getNamesMigrateUsers(self): """Get names migrated users""" return map(lambda x: x[0], filter(lambda x: x[1]=="no",\ zip(self.clVars.Get("cl_migrate_user"), self.clVars.Get("cl_migrate_user_pwd")))) def generateHashUsers(self, stdinRead=False): """Generate pwd hash from users""" addUsers = self.getNamesAddUsers() users = filter(lambda x: x!="root", addUsers) listAddUsers = [] for user in users: hashPwd = self.getPwdHashUser(user, stdinRead) listAddUsers.append((user, hashPwd)) return listAddUsers def generateHashRoot(self, stdinRead=False): """Generate pwd hash from root""" addUsers = self.getNamesAddUsers() if filter(lambda x: x=="root", addUsers): hashPwd = self.getPwdHashUser("root", stdinRead) return [("root", hashPwd,"","")] else: return [] def printMessageForTest(self, message, lenMsg=False): """Print waiting message and OK or Error by func result""" message = "%s ..." % message self.printSUCCESS(message,printBR=False) self.startMessage = message if lenMsg: self.lenStartMessage = lenMsg else: self.lenStartMessage = self.lenString(self.startMessage) def printOnlyNotOK(self, string, offsetL=0, printBR=True): """Вывод на печать в случае сбоя""" self._printSysOut = sys.stdout self.printLine((('', string),), (('blueBr','['), ('redBr',' !! '), ('blueBr',']'), ), offsetL, printBR) def printByResult(self,result,failMessage=None): if self.startMessage: offset = 3 if result: self.printOnlyOK(" ", self.lenStartMessage + offset) else: self.printOnlyNotOK(" ", self.lenStartMessage + offset) if failMessage: self.printERROR(failMessage) self.startMessage = "" self.lenStartMessage = 0 def setupOpenGL(self): """Setup opengl for current video driver""" defaultGL = "xorg-x11" pathGlModules = path.join(self.clVars.Get('cl_chroot_path'), 'usr/lib/opengl') openGLenv = path.join(self.clVars.Get('cl_chroot_path'), 'etc/env.d/03opengl') openGlMods = filter(lambda x:x != "global", listDirectory(pathGlModules)) mapGL_drivers = {'fglrx':"ati" if "ati" in openGlMods else defaultGL, 'nvidia':"nvidia" if "nvidia" in openGlMods else defaultGL} x11_driver = self.clVars.Get('os_install_x11_video_drv') if x11_driver in mapGL_drivers: newModuleName = mapGL_drivers[x11_driver] else: newModuleName = defaultGL curModuleName = map(lambda x:x.strip().rpartition('=')[-1].strip('"\''), filter(lambda x: x.startswith("OPENGL_PROFILE="), open(openGLenv,'r'))) curModuleName = curModuleName[-1] if curModuleName else "" if curModuleName == newModuleName: return True res,errmes = runOsCommand('eselect opengl set %s'%newModuleName) if res == 0: return True else: return False def checkVideoDriver(self): """Check video driver and install nvidia driver""" binPackages = '/usr/portage/packages' nvidiaBinDrivers = path.join(binPackages,'x11-drivers') if self.clVars.Get('hr_video') != 'nvidia' or \ not path.exists(nvidiaBinDrivers): return True maskFile = '/etc/portage/package.mask' nvidiaMaskFile = path.join(maskFile,'nvidia-drivers') # convert file package.mask to directory package mask if path.isfile(maskFile): os.rename(maskFile,maskFile+"2") os.mkdir(maskFile,mode=0755) os.rename(maskFile+"2",path.join(maskFile,"default")) if path.exists(nvidiaMaskFile): curNvidiaMask = open(nvidiaMaskFile,'r').read().strip() else: curNvidiaMask = "" maskNvidia = self.clVars.Get('os_nvidia_mask') if maskNvidia == curNvidiaMask: return True self.printByResult(True) self.printMessageForTest(_("Driver installation for %s")% self.clVars.Get('hr_video')) open(nvidiaMaskFile,'w').write(maskNvidia) try: envDict = {'PKGDIR':binPackages} envDict.update(os.environ) processEmerge = process('/usr/bin/emerge','-k','nvidia-drivers', envdict=envDict,stdout=PIPE,stderr=PIPE) res = processEmerge.success() except KeyboardInterrupt: self.setSignalInterrupt() os.unlink(nvidiaMaskFile) return False if not res: os.unlink(nvidiaMaskFile) return res def hideStdout(self): if not self.stdoutHide: self.stdoutHide = sys.stdout self.stderrHide = sys.stderr sys.stdout = StringIO() sys.stderr = StringIO() sys.stdout.fileno = self.stdoutHide.fileno sys.stderr.fileno = self.stderrHide.fileno def showStdout(self): if self.stdoutHide: sys.stdout = self.stdoutHide sys.stderr = self.stderrHide self.stdoutHide = None self.stderrHide = None def configureSystem(self,autologin): """configuring the current system""" configureMessage = _("Configure the system") error = None keyInter = None try: try: if autologin: objUsers = currentUsers() if not objUsers.hasUsers(autologin): self.printERROR(_("User %s does not exist")%autologin) else: self.setUsers([],autologin) # install this package self.installPackage() self.printMessageForTest(configureMessage) self.printByResult(self.applyTemplatesStartup()) linuxShortname = self.clVars.Get('os_install_linux_shortname') # install desktop package if linuxShortname in ("CLD","CLS","CLDG","CLDX"): desktopLib = '/usr/lib/calculate-2.2/calculate-desktop/pym' if path.exists(desktopLib): sys.path.insert(0, path.abspath(desktopLib)) from cl_desktop import desktop self.printMessageForTest( _("Enable calculate-desktop " "for package configuration")) self.hideStdout() objDesktop = desktop() objDesktop.createClVars() res = objDesktop.installProg() self.showStdout() self.printByResult(res) # install client package if linuxShortname in ("CLD","CLDG","CLDX"): clientLib = '/usr/lib/calculate-2.2/calculate-client/pym' if path.exists(clientLib): sys.path.insert(0, path.abspath(clientLib)) from cl_client import client self.printMessageForTest( _("Enable calculate-client for package configuration")) objClient = client() objClient.createClVars() self.hideStdout() if hasattr(objClient,"updateEnvFiles") and \ objClient.updateEnvFiles(): objClient.clVars.flIniFile() res = objClient.installProg(onlyEnv=True) self.showStdout() self.printByResult(res) pathGlModules = path.join(self.clVars.Get('cl_chroot_path'), 'usr/lib/opengl') self.printMessageForTest(_("Check the video driver")) self.printByResult(self.checkVideoDriver()) if path.exists(pathGlModules): self.printMessageForTest(_("Configure OpenGL")) self.printByResult(self.setupOpenGL()) # if change video driver, then restore initramfs installDrv = self.clVars.Get('os_install_x11_video_drv') if self.clVars.Get('os_x11_video_drv') != installDrv: initrdPath = path.join('/boot', self.clVars.Get('os_install_initrd')) initrdInstallPath = path.join('/boot', self.clVars.Get('os_install_initrd_install')) needMod = {'radeon':'radeon', 'intel':'i915', 'nouveau':'nouveau'}.get(installDrv,'uvesafb') if not InitRamFs(initrdPath).isModuleInside(needMod): self.printMessageForTest(_("Restoring initramfs")) self.printByResult(InitRamFs(initrdInstallPath)\ .cleanInitRamFs(initrdPath)) oldXdrv = self.clVars.Get('os_x11_video_drv') newXdrv = self.clVars.Get('os_install_x11_video_drv') if oldXdrv != newXdrv: kmsDrv = ("radeon","i915","intel","nouveau","ati") self.defaultPrint("\n") if oldXdrv in kmsDrv or newXdrv in kmsDrv: self.defaultPrint( _("To apply the changes, reboot the system") +".\n") else: self.defaultPrint( _("To apply the changes, restart the X server") +".\n") except (InstallError,DistributiveError),e: error = e except Exception,e: error = "" for i in apply(traceback.format_exception, sys.exc_info()): error += i except KeyboardInterrupt: self.setSignalInterrupt() keyInter = True except KeyboardInterrupt: self.setSignalInterrupt() keyInter = True self.showStdout() if keyInter: if self.startMessage: self.printByResult(False) self.defaultPrint("\n") self.printWARNING(_("System configuration interrupted")) error = _("Configuration manually interrupted") if self.startMessage: self.printByResult(False) if error: for line in filter(lambda x: x,str(error).split('\n')): self.printERROR(line) self.printERROR(_("System configuration failed")) return False return True def cleanInitrd(self): """Clean initrd from needless modules""" # get path to initrd and initrd-install in new system # (/boot/initramfs-...-install,/boot/initramfs-...) chrootPath = path.join(self.clVars.Get('cl_chroot_path'),'boot') initrdPath = path.join(chrootPath,self.clVars.Get('os_install_initrd')) initrdInstallPath = path.join(chrootPath, self.clVars.Get('os_install_initrd_install')) copy2(initrdInstallPath,initrdPath); return True def afterCopyHDDinstall(self,targetDistr, addUsers, changePwdUsers, migrateUsers): """Action performed after distributive copy for hdd install""" # copy clt files from current system self.printMessageForTest(_("Coping clt templates to the new system")) cltCpy = cltCopy(target=targetDistr.getDirectory()) for directory in self.clVars.Get('cl_template_clt_path'): cltCpy.performCopy(directory) self.printByResult(True) self.printMessageForTest( _("Coping configuration files to the new system")) fileMask = r"/etc/udev/rules\.d/70-persistent-net\.rules" if self.clVars.Get('os_root_type') != "livecd": fileMask = "(%s|/etc/ssh/ssh_host_.*)"%fileMask fileCpy = otherfilesCopy(target=targetDistr.getDirectory(), reTest=fileMask) fileCpy.performCopy('/etc') self.printByResult(True) # optimize initrd self.clVars.Set("cl_chroot_path",targetDistr.getDirectory(), True) self.printMessageForTest(_("Creating a new initrd file")) self.printByResult(self.cleanInitrd()) # join templates self.printMessageForTest(_("Updating configuration")) self.applyTemplates(targetDistr.getDirectory(), targetDistr.getBootDirectory()[:-4]) # mount bind mount points self.printByResult(True) self.printMessageForTest(_("Post-install configuration")) targetDistr.postinstallMountBind() self.printByResult(True) # migrate users self.printMessageForTest(_("Migrate users")) objMigrate = migrate(targetDistr.getDirectory()) if not objMigrate.migrate(addUsers,changePwdUsers,migrateUsers): raise InstallError(_("Failed to migrate users to the new system")) self.printByResult(True) def checkCorrectBootRecordDisk(self): """Check boot record disk""" mbr = self.clVars.Get('os_install_mbr') if mbr == "off" or mbr == "": return True tableOnBootDisk = self.varSelect('os_device_table', where="os_device_dev",eq=mbr) if not tableOnBootDisk: self.printERROR(_("Disk '%s' without partition table " "contains no boot record")%mbr) return False return True def installSystem(self, force=False, bootDisk=None, stdinReadPwd=False, builder=False, flagSpinner=True, update=False, pxe=False): """install System by current variable enviroment""" sourceDistr = None targetDistr = None error = None distrCopy = False if not self.checkCorrectBootRecordDisk(): return False if pxe and not self.checkNeedPxePkg(): return False try: rootPartdev = self.clVars.Get('os_install_root_dev') rootPartCmdList = filter(lambda x: x['dev']==rootPartdev, self.listDisksOptions) rootPartCmdDict = rootPartCmdList[0] rootPartFileSystem = self.getFieldByField("format","dev", rootPartdev, firstPrefix="os_install_disk") rootPartIsFormat=rootPartCmdDict['isFormat'] rootPartSystemId=rootPartCmdDict['systemId'] self.printInfo(update=update) targetDistr = self.getTargetDistributive(rootPartdev, buildermode=builder, pxemode=pxe, fileSystem=rootPartFileSystem, isFormat=rootPartIsFormat, systemId=rootPartSystemId) distRep = DistributiveRepository() minver = "10.8" instver = \ getTupleVersion(self.clVars.Get('os_install_linux_ver')) distName = self.clVars.Get('cl_image') if distName and instver < getTupleVersion(minver): self.printERROR( _("Installation is supported for " "system version %s or higher")%minver) distName = "" if distName and (not update or self.cmpInstallVersion()>0): # print info sourceDistr = distRep.getDistributiveByFile(distName) if not force: dialogMessage = _("Continue with the installation of \ the system") + " (yes/no)" try: dialogRes = dialogYesNo(dialogMessage) except KeyboardInterrupt: self.setSignalInterrupt() self.defaultPrint("\n") raise KeyboardInterrupt if dialogRes in (None,False): self.printERROR(_("Installation interrupted")) return False # set Users passwords if self.clVars.Get('os_install_root_type') != "flash" and \ self.clVars.Get('os_install_pxe') != 'on': changePwdUsers = \ self.generateHashRoot(stdinRead=stdinReadPwd) addUsers = self.generateHashUsers(stdinRead=stdinReadPwd) migrateUsers = self.getNamesMigrateUsers() mntpath = '/mnt' if not os.access(mntpath,os.W_OK): raise InstallError( _("Enable to create the directory in '%s'")%mntpath) # cmd options if not pxe: self.printMessageForTest(_("Formating partitions")) targetDistr.performFormat() self.printByResult(True) # install distributive self.printMessageForTest( _("Unpacking the system image into target")) self.defaultPrint(" ") self.lenStartMessage += 1 self.clVars.Get('os_grub_conf') # set spinner flag Distributive.flagSpinner = flagSpinner targetDistr.installFrom(sourceDistr) self.printByResult(True) if self.clVars.Get('os_install_root_type') != "flash" and \ self.clVars.Get('os_install_pxe') != 'on': self.afterCopyHDDinstall(targetDistr, addUsers, changePwdUsers, migrateUsers) else: if self.clVars.Get('os_install_pxe') == 'on': self.printSUCCESS( _("Configure PXE installation")) self.applyTemplatesFlash('/') else: # join templates self.printMessageForTest( _("Configure flash installation")) self.applyTemplatesFlash(targetDistr.getDirectory()) self.printByResult(True) self.closeClTemplate() # change boot config if self.clVars.Get('os_install_mbr'): self.printMessageForTest(_("Preparing system for reboot")) self.prepareBoot(targetDistr) self.printByResult(True) else: return False except (EOFError), e: error = e except (InstallError,DistributiveError),e: error = e #for i in apply(traceback.format_exception, sys.exc_info()): # print i except (Exception),e: error = "" for i in apply(traceback.format_exception, sys.exc_info()): error += i except KeyboardInterrupt,e: self.setSignalInterrupt() self.printByResult(False) self.printWARNING(_("Installation interrupted")) error = _("Installation manually interrupted") if error: self.printByResult(False) try: self.closeClTemplate() if sourceDistr and sourceDistr.childs: self.printMessageForTest(_("Releasing the source distribution")) sourceDistr.close() self.printByResult(True) if targetDistr and targetDistr.childs: self.printMessageForTest(_("Unmount the target system volume")) targetDistr.close() self.printByResult(True) except (InstallError,DistributiveError),e: error = "%s\n%s" % (str(error),_("Unmounting error")) except KeyboardInterrupt,e: self.setSignalInterrupt() pass if error: self.printByResult(False) if error: for line in filter(lambda x: x,str(error).split('\n')): self.printERROR(line) self.printERROR(_("System installation failed")) return False self.printSUCCESS(_("System successfully installed")) return True def setLinuxName(self,shortname): self.clVars.Set('os_install_linux_shortname',shortname,True) def setAllLocaleByLang(self,lang): """Set all locale variable by specified lang""" locale = clLocale() if not lang in self.clVars.Get('os_lang'): return False self.clVars.Set('os_install_locale_lang',lang, True) self.clVars.Set('os_install_locale_locale', locale.getFieldByLang('locale',lang), True) self.clVars.Set('os_install_locale_language', locale.getFieldByLang('language',lang), True) self.clVars.Set('os_install_locale_keymap', locale.getFieldByLang('keymap',lang), True) self.clVars.Set('os_install_locale_dumpkeys', locale.getFieldByLang('dumpkeys_charset',lang), True) self.clVars.Set('os_install_locale_xkb', locale.getFieldByLang('xkblayout',lang), True) return True def installOverlay(self): return True #res,mes = runOsCommand('layman -l -N') #notempty = lambda x:x #if res == 0: # # map(lambda x:x[0], # filter(lambda x:x, # map(lambda x:filter(lambda x:x,x.split())[1:2], # mes))) # return True #else: # raise InstallError(_("Cann't get list layman overlays")) def installPackage(self): """Install this package. Convert Gentoo system to Calculate""" error = None self.printSUCCESS(_("Package installed")) try: self.printMessageForTest( _("Enable calculate-install for package configuration")) self.printByResult(appendProgramToEnvFile(__app__, self.clVars), failMessage= _("Failed to save '%(app)s' to %(path)s") %{'app':__app__, 'path':self.clVars.Get("cl_env_path")[0]}) except (InstallError,DistributiveError),e: error = e except (Exception),e: error = "" for i in apply(traceback.format_exception, sys.exc_info()): error += i except KeyboardInterrupt,e: self.setSignalInterrupt() if self.startMessage: self.printByResult(False) self.defaultPrint("\n") error = _("Package installation interrupted manually") if self.startMessage: self.printByResult(False) if error: for line in filter(lambda x: x,str(error).split('\n')): self.printERROR(line) self.printERROR(_("Failed to install the package")) return False return True def uninstallPackage(self): """Uninstall this package. Convert Calculate system to Gentoo""" error = None self.printSUCCESS(_('Package uninstallation')) try: self.printMessageForTest( _("Disable calculate-install for package configuration")) self.printByResult(removeProgramToEnvFile(__app__, self.clVars), failMessage = _("Failed to remove '%(app)s' to %(path)s")\ %{'app':__app__, 'path':self.clVars.Get("cl_env_path")[0]}) except (InstallError,DistributiveError),e: error = e except (Exception),e: error = "" for i in apply(traceback.format_exception, sys.exc_info()): error += i except KeyboardInterrupt,e: self.setSignalInterrupt() if self.startMessage: self.printByResult(False) self.defaultPrint("\n") error = _("Package uninstallation interrupted manually") if self.startMessage: self.printByResult(False) if error: for line in filter(lambda x: x,str(error).split('\n')): self.printERROR(line) self.printERROR(_("Package uninstallation failed")) return False return True def setIso(self,isoimage): """Set iso image for installation""" imageData = DistributiveRepository()._getfromcontent(isoimage) if "name" in imageData and imageData.get('build','') and \ "march" in imageData: self.clVars.Set('os_install_arch_machine', imageData['march'],True) self.clVars.Set('os_install_linux_build', imageData['build'],True) self.clVars.Set('os_install_linux_ver', imageData['ver'],True) self.setLinuxName(imageData['name'].upper()) self.clVars.Set('cl_image',isoimage,True) return True else: self.printERROR(_("Wrong image file")) return False def setVideo(self,video,startup=False): """Set video driver""" if startup: if not video in getInstalledVideo(prefix="/") and \ not video in ("auto","other"): self.printERROR(_("%s videodriver is unavailable")%video) if video == "nvidia": self.printERROR(_("Install %s driver with:")%"NVidia") self.printERROR(" emerge x11-drivers/nvidia-drivers") if video == "fglrx": self.printERROR(_("Install %s driver with:")%"ATI") self.printERROR(" emerge x11-drivers/ati-drivers") return False self.clVars.Set('os_install_x11_video_drv',video,force=True) return True def setTimezone(self,timezone): """Set timezone""" if not path.exists(path.join("/usr/share/zoneinfo",timezone)) or \ timezone.startswith('/usr/share/zoneinfo'): self.printERROR(_("%s timezone is wrong")%timezone) return False else: self.clVars.Set('os_install_clock_timezone',timezone,force=True) return True def setArchitecture(self,march): """Set architecture by march (support auto keyword)""" if march == "auto": march = getSupportArch()[-1] self.clVars.Set('os_install_arch_machine', march, True) def checkNeedPxePkg(self): """Check need for --pxe packages""" for pkg in ['net-misc/dhcp','net-ftp/tftp-hpa','net-fs/nfs-utils']: if not isPkgInstalled(pkg): self.printERROR( _("You must to install %s package for PXE installation") %pkg) return False return True